diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index 068eec6599ead8..e3532559a32fcc 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -678,6 +678,19 @@ static std::unique_ptr genHTML(const CommentInfo &I) { return std::move(ParagraphComment); } + if (I.Kind == "BlockCommandComment") { + auto BlockComment = std::make_unique(HTMLTag::TAG_DIV); + BlockComment->Children.emplace_back( + std::make_unique(HTMLTag::TAG_DIV, I.Name)); + for (const auto &Child : I.Children) { + std::unique_ptr Node = genHTML(*Child); + if (Node) + BlockComment->Children.emplace_back(std::move(Node)); + } + if (BlockComment->Children.empty()) + return nullptr; + return std::move(BlockComment); + } if (I.Kind == "TextComment") { if (I.Text == "") return nullptr; diff --git a/clang-tools-extra/test/clang-doc/basic-project.test b/clang-tools-extra/test/clang-doc/basic-project.test index 2865ed4446e7ef..7c46c52bae687c 100644 --- a/clang-tools-extra/test/clang-doc/basic-project.test +++ b/clang-tools-extra/test/clang-doc/basic-project.test @@ -56,32 +56,62 @@ // HTML-SHAPE:

class Shape

// HTML-SHAPE:

Defined at line 8 of file {{.*}}Shape.h

+// HTML-SHAPE:
brief
+// HTML-SHAPE:

Abstract base class for shapes.

// HTML-SHAPE:

Provides a common interface for different types of shapes.

// HTML-SHAPE:

Functions

// HTML-SHAPE:

area

// HTML-SHAPE:

public double area()

+// HTML-SHAPE:
brief
+// HTML-SHAPE:

Calculates the area of the shape.

// HTML-SHAPE:

perimeter

// HTML-SHAPE:

public double perimeter()

+// HTML-SHAPE:
brief
+// HTML-SHAPE:

Calculates the perimeter of the shape.

+// HTML-SHAPE:
return
+// HTML-SHAPE:

double The perimeter of the shape.

// HTML-SHAPE:

~Shape

// HTML-SHAPE:

public void ~Shape()

// HTML-SHAPE:

Defined at line 13 of file {{.*}}Shape.h

+// HTML-SHAPE:
brief
+// HTML-SHAPE:

Virtual destructor.

-// HTML-CALC:

class Calculator

-// HTML-CALC:

Defined at line 8 of file {{.*}}Calculator.h

-// HTML-CALC:

Provides basic arithmetic operations.

-// HTML-CALC:

Functions

-// HTML-CALC:

add

-// HTML-CALC:

public int add(int a, int b)

-// HTML-CALC:

Defined at line 3 of file {{.*}}Calculator.cpp

-// HTML-CALC:

subtract

-// HTML-CALC:

public int subtract(int a, int b)

-// HTML-CALC:

Defined at line 7 of file {{.*}}Calculator.cpp

-// HTML-CALC:

multiply

-// HTML-CALC:

public int multiply(int a, int b)

-// HTML-CALC:

Defined at line 11 of file {{.*}}Calculator.cpp

-// HTML-CALC:

divide

-// HTML-CALC:

public double divide(int a, int b)

-// HTML-CALC:

Defined at line 15 of file {{.*}}Calculator.cpp

+// HTML-CALC:

class Calculator

+// HTML-CALC:

Defined at line 8 of file {{.*}}Calculator.h

+// HTML-CALC:
brief
+// HTML-CALC:

A simple calculator class.

+// HTML-CALC:

Provides basic arithmetic operations.

+// HTML-CALC:

Functions

+// HTML-CALC:

add

+// HTML-CALC:

public int add(int a, int b)

+// HTML-CALC:

Defined at line 3 of file {{.*}}Calculator.cpp

+// HTML-CALC:
brief
+// HTML-CALC:

Adds two integers.

+// HTML-CALC:
return
+// HTML-CALC:

int The sum of a and b.

+// HTML-CALC:

subtract

+// HTML-CALC:

public int subtract(int a, int b)

+// HTML-CALC:

Defined at line 7 of file {{.*}}Calculator.cpp

+// HTML-CALC:
brief
+// HTML-CALC:

Subtracts the second integer from the first.

+// HTML-CALC:
return
+// HTML-CALC:

int The result of a - b.

+// HTML-CALC:

multiply

+// HTML-CALC:

public int multiply(int a, int b)

+// HTML-CALC:

Defined at line 11 of file {{.*}}Calculator.cpp

+// HTML-CALC:
brief
+// HTML-CALC:

Multiplies two integers.

+// HTML-CALC:
return
+// HTML-CALC:

int The product of a and b.

+// HTML-CALC:

divide

+// HTML-CALC:

public double divide(int a, int b)

+// HTML-CALC:

Defined at line 15 of file {{.*}}Calculator.cpp

+// HTML-CALC:
brief
+// HTML-CALC:

Divides the first integer by the second.

+// HTML-CALC:
return
+// HTML-CALC:

double The result of a / b.

+// HTML-CALC:
throw
+// HTML-CALC:

if b is zero.

// HTML-RECTANGLE:

class Rectangle

// HTML-RECTANGLE:

Defined at line 10 of file {{.*}}Rectangle.h

@@ -99,15 +129,27 @@ // HTML-RECTANGLE:

Rectangle

// HTML-RECTANGLE:

public void Rectangle(double width, double height)

// HTML-RECTANGLE:

Defined at line 3 of file {{.*}}Rectangle.cpp

+// HTML-RECTANGLE:
brief
+// HTML-RECTANGLE:

Constructs a new Rectangle object.

// HTML-RECTANGLE:

area

// HTML-RECTANGLE:

public double area()

// HTML-RECTANGLE:

Defined at line 6 of file {{.*}}Rectangle.cpp

+// HTML-RECTANGLE:
brief
+// HTML-RECTANGLE:

Calculates the area of the rectangle.

+// HTML-RECTANGLE:
return
+// HTML-RECTANGLE:

double The area of the rectangle.

// HTML-RECTANGLE:

perimeter

// HTML-RECTANGLE:

public double perimeter()

// HTML-RECTANGLE:

Defined at line 10 of file {{.*}}Rectangle.cpp

+// HTML-RECTANGLE:
brief
+// HTML-RECTANGLE:

Calculates the perimeter of the rectangle.

+// HTML-RECTANGLE:
return
+// HTML-RECTANGLE:

double The perimeter of the rectangle.

// HTML-CIRCLE:

class Circle

// HTML-CIRCLE:

Defined at line 10 of file {{.*}}Circle.h

+// HTML-CIRCLE:
brief
+// HTML-CIRCLE:

Circle class derived from Shape.

// HTML-CIRCLE:

Represents a circle with a given radius.

// HTML-CIRCLE:

// HTML-CIRCLE: Inherits from @@ -120,12 +162,22 @@ // HTML-CIRCLE:

Circle

// HTML-CIRCLE:

public void Circle(double radius)

// HTML-CIRCLE:

Defined at line 3 of file {{.*}}Circle.cpp

+// HTML-CIRCLE:
brief
+// HTML-CIRCLE:

Constructs a new Circle object.

// HTML-CIRCLE:

area

// HTML-CIRCLE:

public double area()

// HTML-CIRCLE:

Defined at line 5 of file {{.*}}Circle.cpp

+// HTML-CIRCLE:
brief
+// HTML-CIRCLE:

Calculates the area of the circle.

+// HTML-CIRCLE:
return
+// HTML-CIRCLE:

double The area of the circle.

// HTML-CIRCLE:

perimeter

// HTML-CIRCLE:

public double perimeter()

// HTML-CIRCLE:

Defined at line 9 of file {{.*}}Circle.cpp

+// HTML-CIRCLE:
brief
+// HTML-CIRCLE:

Calculates the perimeter of the circle.

+// HTML-CIRCLE:
return
+// HTML-CIRCLE:

double The perimeter of the circle.

// MD-CALC: # class Calculator // MD-CALC: *Defined at .{{[\/]}}include{{[\/]}}Calculator.h#8* diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 131b83ae8eb397..0af473f9bd0802 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -214,7 +214,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0), QualType(FromMP->getClass(), 0)); - if (!this->visit(SubExpr)) + if (!this->delegate(SubExpr)) return false; return this->emitGetMemberPtrBasePop(DerivedOffset, CE); @@ -229,14 +229,14 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0), QualType(ToMP->getClass(), 0)); - if (!this->visit(SubExpr)) + if (!this->delegate(SubExpr)) return false; return this->emitGetMemberPtrBasePop(-DerivedOffset, CE); } case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { - if (!this->visit(SubExpr)) + if (!this->delegate(SubExpr)) return false; const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * { @@ -265,7 +265,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { } case CK_BaseToDerived: { - if (!this->visit(SubExpr)) + if (!this->delegate(SubExpr)) return false; unsigned DerivedOffset = diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index bad46e98304845..b805b7b246c51b 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1568,7 +1568,7 @@ inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) { if (!CheckSubobject(S, OpPC, Ptr, CSK_Base)) return false; const Pointer &Result = Ptr.atField(Off); - if (Result.isPastEnd()) + if (Result.isPastEnd() || !Result.isBaseClass()) return false; S.Stk.push(Result); return true; @@ -1581,7 +1581,7 @@ inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) { if (!CheckSubobject(S, OpPC, Ptr, CSK_Base)) return false; const Pointer &Result = Ptr.atField(Off); - if (Result.isPastEnd()) + if (Result.isPastEnd() || !Result.isBaseClass()) return false; S.Stk.push(Result); return true; diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index b179298fee9bde..1cff2228cd7a97 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -193,6 +193,51 @@ namespace isfpclass { char isfpclass_snan_3 [!__builtin_isfpclass(__builtin_nans(""), 0x01F8) ? 1 : -1]; // fcFinite } +namespace signbit { + static_assert( + !__builtin_signbit(1.0) && __builtin_signbit(-1.0) && !__builtin_signbit(0.0) && __builtin_signbit(-0.0) && + !__builtin_signbitf(1.0f) && __builtin_signbitf(-1.0f) && !__builtin_signbitf(0.0f) && __builtin_signbitf(-0.0f) && + !__builtin_signbitl(1.0L) && __builtin_signbitf(-1.0L) && !__builtin_signbitf(0.0L) && __builtin_signbitf(-0.0L) && + !__builtin_signbit(1.0f) && __builtin_signbit(-1.0f) && !__builtin_signbit(0.0f) && __builtin_signbit(-0.0f) && + !__builtin_signbit(1.0L) && __builtin_signbit(-1.0L) && !__builtin_signbit(0.0L) && __builtin_signbit(-0.0L) && + true, "" + ); +} + +namespace floating_comparison { +#define LESS(X, Y) \ + !__builtin_isgreater(X, Y) && __builtin_isgreater(Y, X) && \ + !__builtin_isgreaterequal(X, Y) && __builtin_isgreaterequal(Y, X) && \ + __builtin_isless(X, Y) && !__builtin_isless(Y, X) && \ + __builtin_islessequal(X, Y) && !__builtin_islessequal(Y, X) && \ + __builtin_islessgreater(X, Y) && __builtin_islessgreater(Y, X) && \ + !__builtin_isunordered(X, Y) && !__builtin_isunordered(Y, X) +#define EQUAL(X, Y) \ + !__builtin_isgreater(X, Y) && !__builtin_isgreater(Y, X) && \ + __builtin_isgreaterequal(X, Y) && __builtin_isgreaterequal(Y, X) && \ + !__builtin_isless(X, Y) && !__builtin_isless(Y, X) && \ + __builtin_islessequal(X, Y) && __builtin_islessequal(Y, X) && \ + !__builtin_islessgreater(X, Y) && !__builtin_islessgreater(Y, X) && \ + !__builtin_isunordered(X, Y) && !__builtin_isunordered(Y, X) +#define UNORDERED(X, Y) \ + !__builtin_isgreater(X, Y) && !__builtin_isgreater(Y, X) && \ + !__builtin_isgreaterequal(X, Y) && !__builtin_isgreaterequal(Y, X) && \ + !__builtin_isless(X, Y) && !__builtin_isless(Y, X) && \ + !__builtin_islessequal(X, Y) && !__builtin_islessequal(Y, X) && \ + !__builtin_islessgreater(X, Y) && !__builtin_islessgreater(Y, X) && \ + __builtin_isunordered(X, Y) && __builtin_isunordered(Y, X) + + static_assert( + LESS(0.0, 1.0) && EQUAL(1.0, 1.0) && EQUAL(0.0, -0.0) && + UNORDERED(__builtin_nan(""), 1.0) && UNORDERED(__builtin_nan(""), __builtin_inf()) && LESS(0.0, __builtin_inf()) && + LESS(0.0f, 1.0f) && EQUAL(1.0f, 1.0f) && EQUAL(0.0f, -0.0f) && + UNORDERED(__builtin_nanf(""), 1.0f) && UNORDERED(__builtin_nanf(""), __builtin_inff()) && LESS(0.0f, __builtin_inff()) && + LESS(0.0L, 1.0L) && EQUAL(1.0L, 1.0L) && EQUAL(0.0L, -0.0L) && + UNORDERED(__builtin_nanl(""), 1.0L) && UNORDERED(__builtin_nanl(""), __builtin_infl()) && LESS(0.0L, __builtin_infl()) && + true, "" + ); +} + namespace fpclassify { char classify_nan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nan(""))]; char classify_snan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nans(""))]; diff --git a/clang/test/CodeGenCoroutines/coro-dwarf-O2.cpp b/clang/test/CodeGenCoroutines/coro-dwarf-O2.cpp new file mode 100644 index 00000000000000..53f4a07982e427 --- /dev/null +++ b/clang/test/CodeGenCoroutines/coro-dwarf-O2.cpp @@ -0,0 +1,39 @@ +// Check that we can still observe the value of the coroutine frame +// with optimizations. +// +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \ +// RUN: -emit-llvm %s -debug-info-kind=limited -dwarf-version=5 \ +// RUN: -O2 -o - | FileCheck %s + +#include "Inputs/coroutine.h" + +template <> +struct std::coroutine_traits { + struct promise_type { + void get_return_object(); + std::suspend_always initial_suspend(); + std::suspend_always final_suspend() noexcept; + void return_void(); + void unhandled_exception(); + }; +}; + +struct ScalarAwaiter { + template void await_suspend(F); + bool await_ready(); + int await_resume(); +}; + +extern "C" void UseScalar(int); + +extern "C" void f() { + UseScalar(co_await ScalarAwaiter{}); + + int Val = co_await ScalarAwaiter{}; + + co_await ScalarAwaiter{}; +} + +// CHECK: define {{.*}}@f.resume({{.*}} %[[ARG:.*]]) +// CHECK: #dbg_value(ptr %[[ARG]], ![[CORO_NUM:[0-9]+]], !DIExpression(DW_OP_deref) +// CHECK: ![[CORO_NUM]] = !DILocalVariable(name: "__coro_frame" diff --git a/clang/test/Modules/merge-using-decls.cpp b/clang/test/Modules/merge-using-decls.cpp index e9794a40837ef9..b678eb4e0f851f 100644 --- a/clang/test/Modules/merge-using-decls.cpp +++ b/clang/test/Modules/merge-using-decls.cpp @@ -8,6 +8,7 @@ // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++11 %s -DORDER=2 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++17 %s -DORDER=2 +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -fmodules -fimplicit-module-maps -fexperimental-new-constant-interpreter -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-using-decls -verify -std=c++98 %s -DORDER=1 #if ORDER == 1 #include "a.h" diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index f4efcf2266cd6b..ff8ad1e619116f 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -126,9 +126,13 @@ DefinedImportThunk::DefinedImportThunk(COFFLinkerContext &ctx, StringRef name, Defined *Undefined::getWeakAlias() { // A weak alias may be a weak alias to another symbol, so check recursively. - for (Symbol *a = weakAlias; a; a = cast(a)->weakAlias) + DenseSet weakChain; + for (Symbol *a = weakAlias; a; a = cast(a)->weakAlias) { if (auto *d = dyn_cast(a)) return d; + if (!weakChain.insert(a).second) + break; // We have a cycle. + } return nullptr; } diff --git a/lld/test/COFF/weak-external-cycle.test b/lld/test/COFF/weak-external-cycle.test new file mode 100644 index 00000000000000..65f483350790f7 --- /dev/null +++ b/lld/test/COFF/weak-external-cycle.test @@ -0,0 +1,41 @@ +REQUIRES: x86 +RUN: split-file %s %t.dir && cd %t.dir + +RUN: llvm-mc -filetype=obj -triple=x86_64-windows test.s -o test.obj +RUN: llvm-mc -filetype=obj -triple=x86_64-windows sym2.s -o sym2.obj +RUN: llvm-mc -filetype=obj -triple=x86_64-windows def.s -o def.obj + +RUN: not lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj sym2.obj 2>&1 | FileCheck -check-prefix=ERR %s + +ERR: error: undefined symbol: testsym +ERR-NEXT: >>> referenced by test.obj +ERR-EMPTY: +ERR-NEXT: error: undefined symbol: sym1 +ERR-NEXT: >>> referenced by test.obj +ERR-NEXT: >>> referenced by sym2.obj +ERR-EMPTY: +ERR-NEXT: error: undefined symbol: sym2 +ERR-NEXT: >>> referenced by test.obj +ERR-NEXT: >>> referenced by sym2.obj + +Depending on symbol processing order, we may have temporary weak reference cycles: + +RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj sym2.obj def.obj +RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll test.obj def.obj sym2.obj +RUN: lld-link -machine:amd64 -dll -noentry -out:test.dll def.obj test.obj sym2.obj + +#--- test.s + .weak testsym +.set testsym, sym1 + .weak sym1 +.set sym1, sym2 + +#--- sym2.s + .weak sym2 +.set sym2, sym1 + +#--- def.s + .globl sym1 + .data +sym1: + .word 0 diff --git a/lld/test/ELF/exclude-libs.s b/lld/test/ELF/exclude-libs.s index 513eb20ba6b482..c25c1eddc2e0d1 100644 --- a/lld/test/ELF/exclude-libs.s +++ b/lld/test/ELF/exclude-libs.s @@ -3,7 +3,7 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ // RUN: %p/Inputs/exclude-libs.s -o %t2.o -// RUN: llvm-as --data-layout=elf %p/Inputs/exclude-libs.ll -o %t3.o +// RUN: llvm-as --data-layout=e %p/Inputs/exclude-libs.ll -o %t3.o // RUN: mkdir -p %t.dir // RUN: rm -f %t.dir/exc.a // RUN: llvm-ar rcs %t.dir/exc.a %t2.o %t3.o diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index 3d908047f9455b..728fe04d14d927 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -342,7 +342,7 @@ uint32_t SBBreakpoint::GetIgnoreCount() const { return count; } -void SBBreakpoint::SetThreadID(tid_t tid) { +void SBBreakpoint::SetThreadID(lldb::tid_t tid) { LLDB_INSTRUMENT_VA(this, tid); BreakpointSP bkpt_sp = GetSP(); @@ -353,10 +353,10 @@ void SBBreakpoint::SetThreadID(tid_t tid) { } } -tid_t SBBreakpoint::GetThreadID() { +lldb::tid_t SBBreakpoint::GetThreadID() { LLDB_INSTRUMENT_VA(this); - tid_t tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp index 75b66364d4f1ae..fad9a4076a54fb 100644 --- a/lldb/source/API/SBBreakpointLocation.cpp +++ b/lldb/source/API/SBBreakpointLocation.cpp @@ -302,7 +302,7 @@ bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) { return has_commands; } -void SBBreakpointLocation::SetThreadID(tid_t thread_id) { +void SBBreakpointLocation::SetThreadID(lldb::tid_t thread_id) { LLDB_INSTRUMENT_VA(this, thread_id); BreakpointLocationSP loc_sp = GetSP(); @@ -313,10 +313,10 @@ void SBBreakpointLocation::SetThreadID(tid_t thread_id) { } } -tid_t SBBreakpointLocation::GetThreadID() { +lldb::tid_t SBBreakpointLocation::GetThreadID() { LLDB_INSTRUMENT_VA(this); - tid_t tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; BreakpointLocationSP loc_sp = GetSP(); if (loc_sp) { std::lock_guard guard( diff --git a/lldb/source/API/SBBreakpointName.cpp b/lldb/source/API/SBBreakpointName.cpp index 7f63aaf6fa7d5e..5c7c0a8f6504b0 100644 --- a/lldb/source/API/SBBreakpointName.cpp +++ b/lldb/source/API/SBBreakpointName.cpp @@ -347,7 +347,7 @@ bool SBBreakpointName::GetAutoContinue() { return bp_name->GetOptions().IsAutoContinue(); } -void SBBreakpointName::SetThreadID(tid_t tid) { +void SBBreakpointName::SetThreadID(lldb::tid_t tid) { LLDB_INSTRUMENT_VA(this, tid); BreakpointName *bp_name = GetBreakpointName(); @@ -361,7 +361,7 @@ void SBBreakpointName::SetThreadID(tid_t tid) { UpdateName(*bp_name); } -tid_t SBBreakpointName::GetThreadID() { +lldb::tid_t SBBreakpointName::GetThreadID() { LLDB_INSTRUMENT_VA(this); BreakpointName *bp_name = GetBreakpointName(); diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 444e44b3928919..22d899f799d0fd 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -130,9 +130,10 @@ static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx, /// Return the length in bytes of the set of operands for \p op. No guarantees /// are made on the state of \p data after this call. -static offset_t GetOpcodeDataSize(const DataExtractor &data, - const lldb::offset_t data_offset, - const uint8_t op, const DWARFUnit *dwarf_cu) { +static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op, + const DWARFUnit *dwarf_cu) { lldb::offset_t offset = data_offset; switch (op) { case DW_OP_addr: @@ -358,7 +359,7 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, error = true; break; } - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) { error = true; @@ -418,7 +419,7 @@ bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu, m_data.SetData(encoder.GetDataBuffer()); return true; } - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) break; @@ -435,7 +436,7 @@ bool DWARFExpression::ContainsThreadLocalStorage( if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) return true; - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) return false; @@ -515,7 +516,7 @@ bool DWARFExpression::LinkThreadLocalStorage( } if (!decoded_data) { - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) return false; diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index eac058701313b8..feabd90dd5a4f3 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -641,7 +641,7 @@ class ReturnValueExtractor { DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size); - offset_t offset = 0; + lldb::offset_t offset = 0; std::optional byte_size = type.GetByteSize(m_process_sp.get()); if (!byte_size) return {}; diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index 20e5652c65bf88..26abea0fdd24d6 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -256,7 +256,7 @@ DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) { if (process->ReadMemoryFromInferior (kernel_addresses_64[i], uval, 8, read_err) == 8) { DataExtractor data (&uval, 8, process->GetByteOrder(), process->GetAddressByteSize()); - offset_t offset = 0; + lldb::offset_t offset = 0; uint64_t addr = data.GetU64 (&offset); if (CheckForKernelImageAtAddress(addr, process).IsValid()) { return addr; @@ -270,7 +270,7 @@ DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) { if (process->ReadMemoryFromInferior (kernel_addresses_32[i], uval, 4, read_err) == 4) { DataExtractor data (&uval, 4, process->GetByteOrder(), process->GetAddressByteSize()); - offset_t offset = 0; + lldb::offset_t offset = 0; uint32_t addr = data.GetU32 (&offset); if (CheckForKernelImageAtAddress(addr, process).IsValid()) { return addr; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index 3863b6b3520db4..624848dee6ec33 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -1151,7 +1151,7 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, // TLS data for the pthread_key on a specific thread yet. If we have we // can re-use it since its location will not change unless the process // execs. - const tid_t tid = thread_sp->GetID(); + const lldb::tid_t tid = thread_sp->GetID(); auto tid_pos = m_tid_to_tls_map.find(tid); if (tid_pos != m_tid_to_tls_map.end()) { auto tls_pos = tid_pos->second.find(key); diff --git a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp index b7cd2b1ac6bf6d..e67e60b4a3957c 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp @@ -261,7 +261,8 @@ InstrumentationRuntimeMainThreadChecker::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP thread_id_obj = info->GetObjectForDotSeparatedPath("tid"); - tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; + lldb::tid_t tid = + thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; // We gather symbolication addresses above, so no need for HistoryThread to // try to infer the call addresses. diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp index b2781aa5e7db15..5516de19d8630b 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp @@ -770,15 +770,15 @@ std::string InstrumentationRuntimeTSan::GetLocationDescription( Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); } } else if (type == "stack") { - tid_t tid = loc->GetAsDictionary() - ->GetValueForKey("thread_id") - ->GetUnsignedIntegerValue(); + lldb::tid_t tid = loc->GetAsDictionary() + ->GetValueForKey("thread_id") + ->GetUnsignedIntegerValue(); result = Sprintf("Location is stack of thread %d", tid); } else if (type == "tls") { - tid_t tid = loc->GetAsDictionary() - ->GetValueForKey("thread_id") - ->GetUnsignedIntegerValue(); + lldb::tid_t tid = loc->GetAsDictionary() + ->GetValueForKey("thread_id") + ->GetUnsignedIntegerValue(); result = Sprintf("Location is TLS of thread %d", tid); } else if (type == "fd") { @@ -948,7 +948,7 @@ static std::string GenerateThreadName(const std::string &path, if (path == "mops") { size_t size = o->GetObjectForDotSeparatedPath("size")->GetUnsignedIntegerValue(); - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); bool is_write = o->GetObjectForDotSeparatedPath("is_write")->GetBooleanValue(); @@ -979,7 +979,7 @@ static std::string GenerateThreadName(const std::string &path, } if (path == "threads") { - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); result = Sprintf("Thread %zu created", thread_id); } @@ -987,7 +987,7 @@ static std::string GenerateThreadName(const std::string &path, if (path == "locs") { std::string type = std::string( o->GetAsDictionary()->GetValueForKey("type")->GetStringValue()); - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); int fd = o->GetObjectForDotSeparatedPath("file_descriptor") ->GetSignedIntegerValue(); @@ -1007,7 +1007,7 @@ static std::string GenerateThreadName(const std::string &path, } if (path == "stacks") { - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); result = Sprintf("Thread %" PRIu64, thread_id); } @@ -1034,7 +1034,7 @@ static void AddThreadsForPath(const std::string &path, StructuredData::ObjectSP thread_id_obj = o->GetObjectForDotSeparatedPath("thread_os_id"); - tid_t tid = + lldb::tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; ThreadSP new_thread_sp = diff --git a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp index 1c58922e8d36c8..80935915e6c67f 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp @@ -321,7 +321,8 @@ InstrumentationRuntimeUBSan::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP thread_id_obj = info->GetObjectForDotSeparatedPath("tid"); - tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; + lldb::tid_t tid = + thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; // We gather symbolication addresses above, so no need for HistoryThread to // try to infer the call addresses. diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp index 6efd2516578ff2..fe6c5a0544be32 100644 --- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp +++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -107,7 +107,7 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, return; int count = count_sp->GetValueAsUnsigned(0); - tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1; + lldb::tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1; if (count <= 0) return; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 22ece4f4dacf79..327069bd9135de 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5673,7 +5673,8 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, return false; } -bool ObjectFileMachO::GetCorefileThreadExtraInfos(std::vector &tids) { +bool ObjectFileMachO::GetCorefileThreadExtraInfos( + std::vector &tids) { tids.clear(); ModuleSP module_sp(GetModule()); if (module_sp) { @@ -5724,8 +5725,8 @@ bool ObjectFileMachO::GetCorefileThreadExtraInfos(std::vector &tids) { return false; } StructuredData::Dictionary *thread = *maybe_thread; - tid_t tid = LLDB_INVALID_THREAD_ID; - if (thread->GetValueForKeyAsInteger("thread_id", tid)) + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + if (thread->GetValueForKeyAsInteger("thread_id", tid)) if (tid == 0) tid = LLDB_INVALID_THREAD_ID; tids.push_back(tid); diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index e026ffefd645ee..106e38b6e25ae3 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -227,7 +227,7 @@ ThreadSP OperatingSystemPython::CreateThreadFromThreadInfo( ThreadList &old_thread_list, std::vector &core_used_map, bool *did_create_ptr) { ThreadSP thread_sp; - tid_t tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; if (!thread_dict.GetValueForKeyAsInteger("tid", tid)) return ThreadSP(); diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 89ecc757a68f56..550b53688fd39e 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -20,7 +20,7 @@ using namespace lldb; using namespace lldb_private; -ThreadMemory::ThreadMemory(Process &process, tid_t tid, +ThreadMemory::ThreadMemory(Process &process, lldb::tid_t tid, const ValueObjectSP &thread_info_valobj_sp) : Thread(process, tid), m_backing_thread_sp(), m_thread_info_valobj_sp(thread_info_valobj_sp), m_name(), m_queue(), diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index c7ce368ab41ce2..0efe8fb238491e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1513,7 +1513,7 @@ bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list, ThreadList old_thread_list_copy(old_thread_list); if (num_thread_ids > 0) { for (size_t i = 0; i < num_thread_ids; ++i) { - tid_t tid = m_thread_ids[i]; + lldb::tid_t tid = m_thread_ids[i]; ThreadSP thread_sp( old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); if (!thread_sp) { diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index 1da7696c9a352a..930c707604bb38 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -593,19 +593,19 @@ bool ProcessMachCore::DoUpdateThreadList(ThreadList &old_thread_list, ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); if (core_objfile) { - std::set used_tids; + std::set used_tids; const uint32_t num_threads = core_objfile->GetNumThreadContexts(); - std::vector tids; + std::vector tids; if (core_objfile->GetCorefileThreadExtraInfos(tids)) { assert(tids.size() == num_threads); // Find highest tid value. - tid_t highest_tid = 0; + lldb::tid_t highest_tid = 0; for (uint32_t i = 0; i < num_threads; i++) { if (tids[i] != LLDB_INVALID_THREAD_ID && tids[i] > highest_tid) highest_tid = tids[i]; } - tid_t current_unused_tid = highest_tid + 1; + lldb::tid_t current_unused_tid = highest_tid + 1; for (uint32_t i = 0; i < num_threads; i++) { if (tids[i] == LLDB_INVALID_THREAD_ID) { tids[i] = current_unused_tid++; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 81f937762e35a6..feb72f6244a18c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -1023,7 +1023,7 @@ uint32_t DWARFUnit::GetHeaderByteSize() const { std::optional DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { - offset_t offset = GetStrOffsetsBase() + index * 4; + lldb::offset_t offset = GetStrOffsetsBase() + index * 4; return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); } diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp index 2064b73dc3ea5b..824528fc3acfa2 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp @@ -216,7 +216,7 @@ lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction( AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread, - tid_t thread_id, + lldb::tid_t thread_id, addr_t page_to_free, uint64_t page_to_free_size, Status &error) { diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp index f3df8a2c27f5ac..ff2610c9df2765 100644 --- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -33,7 +33,7 @@ using namespace lldb_private::dwarf; // Used for calls when the value type is specified by a DWARF EH Frame pointer // encoding. static uint64_t -GetGNUEHPointer(const DataExtractor &DE, offset_t *offset_ptr, +GetGNUEHPointer(const DataExtractor &DE, lldb::offset_t *offset_ptr, uint32_t eh_ptr_enc, addr_t pc_rel_addr, addr_t text_addr, addr_t data_addr) //, BSDRelocs *data_relocs) const { @@ -588,7 +588,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset, if (cie->augmentation[0] == 'z') { uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) { - offset_t saved_offset = offset; + lldb::offset_t saved_offset = offset; lsda_data_file_address = GetGNUEHPointer(m_cfi_data, &offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr); diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 5e5e9b9e8a93b1..1920ffb7b08d37 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2046,7 +2046,8 @@ example: attributes. ``naked`` This attribute disables prologue / epilogue emission for the - function. This can have very system-specific consequences. + function. This can have very system-specific consequences. The arguments of + a ``naked`` function can not be referenced through IR values. ``"no-inline-line-tables"`` When this attribute is set to true, the inliner discards source locations when inlining code and instead uses the source location of the call site. diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index 5efdaaccf1fc7f..d295d1f5785eb9 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -268,10 +268,6 @@ Expected DataLayout::parse(StringRef LayoutString) { return Layout; } -static Error reportError(const Twine &Message) { - return createStringError(inconvertibleErrorCode(), Message); -} - static Error createSpecFormatError(Twine Format) { return createStringError("malformed specification, must be of the form \"" + Format + "\""); @@ -336,46 +332,6 @@ static Error parseAlignment(StringRef Str, Align &Alignment, StringRef Name, return Error::success(); } -/// Checked version of split, to ensure mandatory subparts. -static Error split(StringRef Str, char Separator, - std::pair &Split) { - assert(!Str.empty() && "parse error, string can't be empty here"); - Split = Str.split(Separator); - if (Split.second.empty() && Split.first != Str) - return reportError("Trailing separator in datalayout string"); - if (!Split.second.empty() && Split.first.empty()) - return reportError("Expected token before separator in datalayout string"); - return Error::success(); -} - -/// Get an unsigned integer, including error checks. -template static Error getInt(StringRef R, IntTy &Result) { - bool error = R.getAsInteger(10, Result); (void)error; - if (error) - return reportError("not a number, or does not fit in an unsigned int"); - return Error::success(); -} - -/// Get an unsigned integer representing the number of bits and convert it into -/// bytes. Error out of not a byte width multiple. -template -static Error getIntInBytes(StringRef R, IntTy &Result) { - if (Error Err = getInt(R, Result)) - return Err; - if (Result % 8) - return reportError("number of bits must be a byte width multiple"); - Result /= 8; - return Error::success(); -} - -static Error getAddrSpace(StringRef R, unsigned &AddrSpace) { - if (Error Err = getInt(R, AddrSpace)) - return Err; - if (!isUInt<24>(AddrSpace)) - return reportError("Invalid address space, must be a 24-bit integer"); - return Error::success(); -} - Error DataLayout::parsePrimitiveSpec(StringRef Spec) { // [ifv]:[:] SmallVector Components; @@ -536,55 +492,45 @@ Error DataLayout::parseSpecification(StringRef Spec) { if (Specifier == 'p') return parsePointerSpec(Spec); - // Split at ':'. - std::pair Split; - if (Error Err = ::split(Spec, ':', Split)) - return Err; - - // Aliases used below. - StringRef &Tok = Split.first; // Current token. - StringRef &Rest = Split.second; // The rest of the string. - - char SpecifierChar = Tok.front(); - Tok = Tok.substr(1); - - switch (SpecifierChar) { + StringRef Rest = Spec.drop_front(); + switch (Specifier) { case 's': // Deprecated, but ignoring here to preserve loading older textual llvm // ASM file break; - case 'E': - BigEndian = true; - break; case 'e': - BigEndian = false; + case 'E': + if (!Rest.empty()) + return createStringError( + "malformed specification, must be just 'e' or 'E'"); + BigEndian = Specifier == 'E'; break; case 'n': // Native integer types. - while (true) { - unsigned Width; - if (Error Err = getInt(Tok, Width)) - return Err; - if (Width == 0) - return reportError( - "Zero width native integer type in datalayout string"); - LegalIntWidths.push_back(Width); - if (Rest.empty()) - break; - if (Error Err = ::split(Rest, ':', Split)) + // n[:]... + for (StringRef Str : split(Rest, ':')) { + unsigned BitWidth; + if (Error Err = parseSize(Str, BitWidth)) return Err; + LegalIntWidths.push_back(BitWidth); } break; case 'S': { // Stack natural alignment. - uint64_t Alignment; - if (Error Err = getIntInBytes(Tok, Alignment)) + // S + if (Rest.empty()) + return createSpecFormatError("S"); + Align Alignment; + if (Error Err = parseAlignment(Rest, Alignment, "stack natural")) return Err; - if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) - return reportError("Alignment is neither 0 nor a power of 2"); - StackNaturalAlign = MaybeAlign(Alignment); + StackNaturalAlign = Alignment; break; } case 'F': { - switch (Tok.front()) { + // F + if (Rest.empty()) + return createSpecFormatError("F"); + char Type = Rest.front(); + Rest = Rest.drop_front(); + switch (Type) { case 'i': TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; break; @@ -592,44 +538,44 @@ Error DataLayout::parseSpecification(StringRef Spec) { TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign; break; default: - return reportError("Unknown function pointer alignment type in " - "datalayout string"); + return createStringError("unknown function pointer alignment type '" + + Twine(Type) + "'"); } - Tok = Tok.substr(1); - uint64_t Alignment; - if (Error Err = getIntInBytes(Tok, Alignment)) + Align Alignment; + if (Error Err = parseAlignment(Rest, Alignment, "ABI")) return Err; - if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) - return reportError("Alignment is neither 0 nor a power of 2"); - FunctionPtrAlign = MaybeAlign(Alignment); + FunctionPtrAlign = Alignment; break; } case 'P': { // Function address space. - if (Error Err = getAddrSpace(Tok, ProgramAddrSpace)) + if (Rest.empty()) + return createSpecFormatError("P
"); + if (Error Err = parseAddrSpace(Rest, ProgramAddrSpace)) return Err; break; } case 'A': { // Default stack/alloca address space. - if (Error Err = getAddrSpace(Tok, AllocaAddrSpace)) + if (Rest.empty()) + return createSpecFormatError("A
"); + if (Error Err = parseAddrSpace(Rest, AllocaAddrSpace)) return Err; break; } case 'G': { // Default address space for global variables. - if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace)) + if (Rest.empty()) + return createSpecFormatError("G
"); + if (Error Err = parseAddrSpace(Rest, DefaultGlobalsAddrSpace)) return Err; break; } case 'm': - if (!Tok.empty()) - return reportError("Unexpected trailing characters after mangling " - "specifier in datalayout string"); - if (Rest.empty()) - return reportError("Expected mangling specifier in datalayout string"); + if (!Rest.consume_front(":") || Rest.empty()) + return createSpecFormatError("m:"); if (Rest.size() > 1) - return reportError("Unknown mangling specifier in datalayout string"); + return createStringError("unknown mangling mode"); switch (Rest[0]) { default: - return reportError("Unknown mangling in datalayout string"); + return createStringError("unknown mangling mode"); case 'e': ManglingMode = MM_ELF; break; @@ -654,7 +600,7 @@ Error DataLayout::parseSpecification(StringRef Spec) { } break; default: - return reportError("Unknown specifier in datalayout string"); + return createStringError("unknown specifier '" + Twine(Specifier) + "'"); } return Error::success(); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 6c89abeed631e4..406d63d9f41d49 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2777,6 +2777,10 @@ void Verifier::visitFunction(const Function &F) { Check(!Attrs.hasAttrSomewhere(Attribute::ElementType), "Attribute 'elementtype' can only be applied to a callsite.", &F); + if (Attrs.hasFnAttr(Attribute::Naked)) + for (const Argument &Arg : F.args()) + Check(Arg.use_empty(), "cannot use argument of naked function", &Arg); + // 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. diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 73e30ea00a0e29..00f49b7bdce294 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -1121,30 +1121,11 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, DIBuilder DBuilder(*F.getParent(), /*AllowUnresolved*/ false); - AllocaInst *PromiseAlloca = Shape.getPromiseAlloca(); - assert(PromiseAlloca && + assert(Shape.getPromiseAlloca() && "Coroutine with switch ABI should own Promise alloca"); - TinyPtrVector DIs = findDbgDeclares(PromiseAlloca); - TinyPtrVector DVRs = findDVRDeclares(PromiseAlloca); - - DILocalVariable *PromiseDIVariable = nullptr; - DILocation *DILoc = nullptr; - if (!DIs.empty()) { - DbgDeclareInst *PromiseDDI = DIs.front(); - PromiseDIVariable = PromiseDDI->getVariable(); - DILoc = PromiseDDI->getDebugLoc().get(); - } else if (!DVRs.empty()) { - DbgVariableRecord *PromiseDVR = DVRs.front(); - PromiseDIVariable = PromiseDVR->getVariable(); - DILoc = PromiseDVR->getDebugLoc().get(); - } else { - return; - } - - DILocalScope *PromiseDIScope = PromiseDIVariable->getScope(); - DIFile *DFile = PromiseDIScope->getFile(); - unsigned LineNum = PromiseDIVariable->getLine(); + DIFile *DFile = DIS->getFile(); + unsigned LineNum = DIS->getLine(); DICompositeType *FrameDITy = DBuilder.createStructType( DIS->getUnit(), Twine(F.getName() + ".coro_frame_ty").str(), @@ -1254,10 +1235,9 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, DBuilder.replaceArrays(FrameDITy, DBuilder.getOrCreateArray(Elements)); - auto *FrameDIVar = DBuilder.createAutoVariable(PromiseDIScope, "__coro_frame", - DFile, LineNum, FrameDITy, - true, DINode::FlagArtificial); - assert(FrameDIVar->isValidLocationForIntrinsic(DILoc)); + auto *FrameDIVar = + DBuilder.createAutoVariable(DIS, "__coro_frame", DFile, LineNum, + FrameDITy, true, DINode::FlagArtificial); // Subprogram would have ContainedNodes field which records the debug // variables it contained. So we need to add __coro_frame to the @@ -1266,14 +1246,17 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, // If we don't add __coro_frame to the RetainedNodes, user may get // `no symbol __coro_frame in context` rather than `__coro_frame` // is optimized out, which is more precise. - if (auto *SubProgram = dyn_cast(PromiseDIScope)) { - auto RetainedNodes = SubProgram->getRetainedNodes(); - SmallVector RetainedNodesVec(RetainedNodes.begin(), - RetainedNodes.end()); - RetainedNodesVec.push_back(FrameDIVar); - SubProgram->replaceOperandWith( - 7, (MDTuple::get(F.getContext(), RetainedNodesVec))); - } + auto RetainedNodes = DIS->getRetainedNodes(); + SmallVector RetainedNodesVec(RetainedNodes.begin(), + RetainedNodes.end()); + RetainedNodesVec.push_back(FrameDIVar); + DIS->replaceOperandWith(7, (MDTuple::get(F.getContext(), RetainedNodesVec))); + + // Construct the location for the frame debug variable. The column number + // is fake but it should be fine. + DILocation *DILoc = + DILocation::get(DIS->getContext(), LineNum, /*Column=*/1, DIS); + assert(FrameDIVar->isValidLocationForIntrinsic(DILoc)); if (UseNewDbgInfoFormat) { DbgVariableRecord *NewDVR = @@ -1931,8 +1914,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { } // This dbg.declare is for the main function entry point. It // will be deleted in all coro-split functions. - coro::salvageDebugInfo(ArgToAllocaMap, *DDI, Shape.OptimizeFrame, - false /*UseEntryValue*/); + coro::salvageDebugInfo(ArgToAllocaMap, *DDI, false /*UseEntryValue*/); }; for_each(DIs, SalvageOne); for_each(DVRs, SalvageOne); @@ -2869,9 +2851,8 @@ static void collectFrameAlloca(AllocaInst *AI, coro::Shape &Shape, static std::optional> salvageDebugInfoImpl(SmallDenseMap &ArgToAllocaMap, - bool OptimizeFrame, bool UseEntryValue, Function *F, - Value *Storage, DIExpression *Expr, - bool SkipOutermostLoad) { + bool UseEntryValue, Function *F, Value *Storage, + DIExpression *Expr, bool SkipOutermostLoad) { IRBuilder<> Builder(F->getContext()); auto InsertPt = F->getEntryBlock().getFirstInsertionPt(); while (isa(InsertPt)) @@ -2923,10 +2904,9 @@ salvageDebugInfoImpl(SmallDenseMap &ArgToAllocaMap, // If the coroutine frame is an Argument, store it in an alloca to improve // its availability (e.g. registers may be clobbered). - // Avoid this if optimizations are enabled (they would remove the alloca) or - // if the value is guaranteed to be available through other means (e.g. swift - // ABI guarantees). - if (StorageAsArg && !OptimizeFrame && !IsSwiftAsyncArg) { + // Avoid this if the value is guaranteed to be available through other means + // (e.g. swift ABI guarantees). + if (StorageAsArg && !IsSwiftAsyncArg) { auto &Cached = ArgToAllocaMap[StorageAsArg]; if (!Cached) { Cached = Builder.CreateAlloca(Storage->getType(), 0, nullptr, @@ -2949,7 +2929,7 @@ salvageDebugInfoImpl(SmallDenseMap &ArgToAllocaMap, void coro::salvageDebugInfo( SmallDenseMap &ArgToAllocaMap, - DbgVariableIntrinsic &DVI, bool OptimizeFrame, bool UseEntryValue) { + DbgVariableIntrinsic &DVI, bool UseEntryValue) { Function *F = DVI.getFunction(); // Follow the pointer arithmetic all the way to the incoming @@ -2957,9 +2937,9 @@ void coro::salvageDebugInfo( bool SkipOutermostLoad = !isa(DVI); Value *OriginalStorage = DVI.getVariableLocationOp(0); - auto SalvagedInfo = ::salvageDebugInfoImpl( - ArgToAllocaMap, OptimizeFrame, UseEntryValue, F, OriginalStorage, - DVI.getExpression(), SkipOutermostLoad); + auto SalvagedInfo = + ::salvageDebugInfoImpl(ArgToAllocaMap, UseEntryValue, F, OriginalStorage, + DVI.getExpression(), SkipOutermostLoad); if (!SalvagedInfo) return; @@ -2991,7 +2971,7 @@ void coro::salvageDebugInfo( void coro::salvageDebugInfo( SmallDenseMap &ArgToAllocaMap, - DbgVariableRecord &DVR, bool OptimizeFrame, bool UseEntryValue) { + DbgVariableRecord &DVR, bool UseEntryValue) { Function *F = DVR.getFunction(); // Follow the pointer arithmetic all the way to the incoming @@ -2999,9 +2979,9 @@ void coro::salvageDebugInfo( bool SkipOutermostLoad = DVR.isDbgDeclare(); Value *OriginalStorage = DVR.getVariableLocationOp(0); - auto SalvagedInfo = ::salvageDebugInfoImpl( - ArgToAllocaMap, OptimizeFrame, UseEntryValue, F, OriginalStorage, - DVR.getExpression(), SkipOutermostLoad); + auto SalvagedInfo = + ::salvageDebugInfoImpl(ArgToAllocaMap, UseEntryValue, F, OriginalStorage, + DVR.getExpression(), SkipOutermostLoad); if (!SalvagedInfo) return; diff --git a/llvm/lib/Transforms/Coroutines/CoroInternal.h b/llvm/lib/Transforms/Coroutines/CoroInternal.h index 5716fd0ea4ab96..d535ad7f85d74a 100644 --- a/llvm/lib/Transforms/Coroutines/CoroInternal.h +++ b/llvm/lib/Transforms/Coroutines/CoroInternal.h @@ -29,14 +29,14 @@ void replaceCoroFree(CoroIdInst *CoroId, bool Elide); /// Attempts to rewrite the location operand of debug intrinsics in terms of /// the coroutine frame pointer, folding pointer offsets into the DIExpression /// of the intrinsic. -/// If the frame pointer is an Argument, store it into an alloca if -/// OptimizeFrame is false. +/// If the frame pointer is an Argument, store it into an alloca to enhance the +/// debugability. void salvageDebugInfo( SmallDenseMap &ArgToAllocaMap, - DbgVariableIntrinsic &DVI, bool OptimizeFrame, bool IsEntryPoint); + DbgVariableIntrinsic &DVI, bool IsEntryPoint); void salvageDebugInfo( SmallDenseMap &ArgToAllocaMap, - DbgVariableRecord &DVR, bool OptimizeFrame, bool UseEntryValue); + DbgVariableRecord &DVR, bool UseEntryValue); // Keeps data and helper functions for lowering coroutine intrinsics. struct LowererBase { diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 8eceaef59a1e1f..40bc932c3e0eef 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -735,11 +735,9 @@ void CoroCloner::salvageDebugInfo() { bool UseEntryValue = llvm::Triple(OrigF.getParent()->getTargetTriple()).isArch64Bit(); for (DbgVariableIntrinsic *DVI : Worklist) - coro::salvageDebugInfo(ArgToAllocaMap, *DVI, Shape.OptimizeFrame, - UseEntryValue); + coro::salvageDebugInfo(ArgToAllocaMap, *DVI, UseEntryValue); for (DbgVariableRecord *DVR : DbgVariableRecords) - coro::salvageDebugInfo(ArgToAllocaMap, *DVR, Shape.OptimizeFrame, - UseEntryValue); + coro::salvageDebugInfo(ArgToAllocaMap, *DVR, UseEntryValue); // Remove all salvaged dbg.declare intrinsics that became // either unreachable or stale due to the CoroSplit transformation. @@ -1962,11 +1960,9 @@ splitCoroutine(Function &F, SmallVectorImpl &Clones, SmallDenseMap ArgToAllocaMap; auto [DbgInsts, DbgVariableRecords] = collectDbgVariableIntrinsics(F); for (auto *DDI : DbgInsts) - coro::salvageDebugInfo(ArgToAllocaMap, *DDI, Shape.OptimizeFrame, - false /*UseEntryValue*/); + coro::salvageDebugInfo(ArgToAllocaMap, *DDI, false /*UseEntryValue*/); for (DbgVariableRecord *DVR : DbgVariableRecords) - coro::salvageDebugInfo(ArgToAllocaMap, *DVR, Shape.OptimizeFrame, - false /*UseEntryValue*/); + coro::salvageDebugInfo(ArgToAllocaMap, *DVR, false /*UseEntryValue*/); return Shape; } diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index d097ae116a0d22..86e50a7f914372 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -7014,7 +7014,7 @@ LoopVectorizationPlanner::plan(ElementCount UserVF, unsigned UserIC) { ElementCount MaxUserVF = UserVF.isScalable() ? MaxFactors.ScalableVF : MaxFactors.FixedVF; - if (!UserVF.isZero()) { + if (UserVF) { if (!ElementCount::isKnownLE(UserVF, MaxUserVF)) { reportVectorizationInfo( "UserVF ignored because it may be larger than the maximal safe VF", diff --git a/llvm/test/Assembler/invalid-datalayout-override.ll b/llvm/test/Assembler/invalid-datalayout-override.ll index f62777c6c53287..28bbbfb99a180d 100644 --- a/llvm/test/Assembler/invalid-datalayout-override.ll +++ b/llvm/test/Assembler/invalid-datalayout-override.ll @@ -4,4 +4,4 @@ ; RUN: llvm-as -data-layout "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" < %s target datalayout = "A16777216" -; CHECK: Invalid address space, must be a 24-bit integer +; CHECK: address space must be a 24-bit integer diff --git a/llvm/test/Bitcode/function-default-address-spaces.ll b/llvm/test/Bitcode/function-default-address-spaces.ll index 3aae5db863b88a..03b4d5c2e04b80 100644 --- a/llvm/test/Bitcode/function-default-address-spaces.ll +++ b/llvm/test/Bitcode/function-default-address-spaces.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s -check-prefixes CHECK,PROG-AS0 ; RUN: llvm-as -data-layout "P200" %s -o - | llvm-dis | FileCheck %s -check-prefixes CHECK,PROG-AS200 ; RUN: not llvm-as -data-layout "P123456789" %s -o /dev/null 2>&1 | FileCheck %s -check-prefix BAD-DATALAYOUT -; BAD-DATALAYOUT: error: Invalid address space, must be a 24-bit integer +; BAD-DATALAYOUT: error: address space must be a 24-bit integer ; PROG-AS0-NOT: target datalayout ; PROG-AS200: target datalayout = "P200" diff --git a/llvm/test/Bitcode/invalid-functionptr-align.ll b/llvm/test/Bitcode/invalid-functionptr-align.ll deleted file mode 100644 index 8b446d371f6fde..00000000000000 --- a/llvm/test/Bitcode/invalid-functionptr-align.ll +++ /dev/null @@ -1,5 +0,0 @@ -; Bitcode with invalid function pointer alignment. - -; RUN: not llvm-dis %s.bc -o - 2>&1 | FileCheck %s - -CHECK: error: Alignment is neither 0 nor a power of 2 diff --git a/llvm/test/Bitcode/invalid-stack-align.ll b/llvm/test/Bitcode/invalid-stack-align.ll new file mode 100644 index 00000000000000..a5cca2ad6be986 --- /dev/null +++ b/llvm/test/Bitcode/invalid-stack-align.ll @@ -0,0 +1,5 @@ +; Bitcode with invalid natural stack alignment. + +; RUN: not llvm-dis %s.bc -o - 2>&1 | FileCheck %s + +CHECK: error: stack natural alignment must be a power of two times the byte width diff --git a/llvm/test/Bitcode/invalid-functionptr-align.ll.bc b/llvm/test/Bitcode/invalid-stack-align.ll.bc similarity index 100% rename from llvm/test/Bitcode/invalid-functionptr-align.ll.bc rename to llvm/test/Bitcode/invalid-stack-align.ll.bc diff --git a/llvm/test/CodeGen/PowerPC/pr15359.ll b/llvm/test/CodeGen/PowerPC/pr15359.ll index c7be78e5c3cead..5c30790f69d703 100644 --- a/llvm/test/CodeGen/PowerPC/pr15359.ll +++ b/llvm/test/CodeGen/PowerPC/pr15359.ll @@ -1,7 +1,7 @@ ; RUN: llc -verify-machineinstrs -O0 -mcpu=pwr7 -filetype=obj %s -o - | \ ; RUN: llvm-readobj --symbols - | FileCheck %s -target datalayout = "E-p:64:64:64-S0-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-n32:64" +target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" @nextIdx = external thread_local global i32 diff --git a/llvm/test/CodeGen/PowerPC/pr16556-2.ll b/llvm/test/CodeGen/PowerPC/pr16556-2.ll index 9b7b3b21ff30bd..8f871cafcf6388 100644 --- a/llvm/test/CodeGen/PowerPC/pr16556-2.ll +++ b/llvm/test/CodeGen/PowerPC/pr16556-2.ll @@ -3,7 +3,7 @@ ; This test formerly failed because of wrong custom lowering for ; fptosi of ppc_fp128. -target datalayout = "E-p:32:32:32-S0-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:64:128-v64:64:64-v128:128:128-a0:0:64-n32" +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:64:128-v64:64:64-v128:128:128-a0:0:64-n32" target triple = "powerpc-unknown-linux-gnu" %core.time.TickDuration = type { i64 } diff --git a/llvm/test/CodeGen/PowerPC/pr16556.ll b/llvm/test/CodeGen/PowerPC/pr16556.ll index 95f4d1df5b27b2..ae680d37639101 100644 --- a/llvm/test/CodeGen/PowerPC/pr16556.ll +++ b/llvm/test/CodeGen/PowerPC/pr16556.ll @@ -2,7 +2,7 @@ ; This test formerly failed due to no handling for a ppc_fp128 undef. -target datalayout = "E-p:32:32:32-S0-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:64:128-v64:64:64-v128:128:128-a0:0:64-n32" +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:64:128-v64:64:64-v128:128:128-a0:0:64-n32" target triple = "powerpc-unknown-linux-gnu" %core.time.TickDuration.37.125 = type { i64 } diff --git a/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll b/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll index 3aef34317b0bbd..5a15cfa6864c4b 100644 --- a/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll +++ b/llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll @@ -98,12 +98,12 @@ define void @SwiftErrorCall(ptr swifterror) sanitize_thread { ret void } -; CHECK-LABEL: @NakedTest(ptr %a) -; CHECK-NEXT: call void @foo() -; CHECK-NEXT: %tmp1 = load i32, ptr %a, align 4 -; CHECK-NEXT: ret i32 %tmp1 -define i32 @NakedTest(ptr %a) naked sanitize_thread { - call void @foo() +; CHECK-LABEL: @NakedTest() +; CHECK-NEXT: %a = call ptr @foo() +; CHECK-NEXT: %tmp1 = load i32, ptr %a, align 4 +; CHECK-NEXT: ret i32 %tmp1 +define i32 @NakedTest() naked sanitize_thread { + %a = call ptr @foo() %tmp1 = load i32, ptr %a, align 4 ret i32 %tmp1 } diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll index d18f5641ef5ba9..990695954a9f60 100644 --- a/llvm/test/Transforms/Attributor/nonnull.ll +++ b/llvm/test/Transforms/Attributor/nonnull.ll @@ -1048,10 +1048,8 @@ define internal void @naked(ptr dereferenceable(4) %a) naked { ; CHECK: Function Attrs: naked ; CHECK-LABEL: define {{[^@]+}}@naked ; CHECK-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] { -; CHECK-NEXT: call void @use_i32_ptr(ptr nocapture nofree noundef nonnull [[A]]) ; CHECK-NEXT: ret void ; - call void @use_i32_ptr(ptr %a) ret void } ; Avoid nonnull as we do not touch optnone diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll index 080ea2e77a7aea..b085e34d52648c 100644 --- a/llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll +++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll @@ -81,6 +81,6 @@ attributes #0 = { ; attributes to drop attributes #1 = { - alignstack=16 convergent inaccessiblememonly inaccessiblemem_or_argmemonly naked + alignstack=16 convergent inaccessiblememonly inaccessiblemem_or_argmemonly noreturn readonly argmemonly returns_twice speculatable "thunk" } diff --git a/llvm/test/Transforms/Coroutines/coro-debug-O2.ll b/llvm/test/Transforms/Coroutines/coro-debug-O2.ll index 7ffa2ac153c853..588f47959cc5d5 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug-O2.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug-O2.ll @@ -1,12 +1,14 @@ ; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),function(sroa)' -S | FileCheck %s ; RUN: opt --try-experimental-debuginfo-iterators < %s -passes='module(coro-early),cgscc(coro-split),function(sroa)' -S | FileCheck %s -; Checks whether the dbg.declare for `__promise` remains valid under O2. +; Checks the dbg informations about promise and coroutine frames under O2. ; CHECK-LABEL: define internal fastcc void @f.resume({{.*}}) ; CHECK: entry.resume: -; CHECK: #dbg_declare(ptr %begin, ![[PROMISEVAR_RESUME:[0-9]+]], !DIExpression( +; CHECK: #dbg_value(ptr poison, ![[PROMISEVAR_RESUME:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16 +; CHECK: #dbg_value(ptr %begin, ![[CORO_FRAME:[0-9]+]], !DIExpression(DW_OP_deref) ; +; CHECK: ![[CORO_FRAME]] = !DILocalVariable(name: "__coro_frame" ; CHECK: ![[PROMISEVAR_RESUME]] = !DILocalVariable(name: "__promise" %promise_type = type { i32, i32, double } diff --git a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll index 8e5c4ab52e78eb..1d668fd0222f77 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll @@ -15,8 +15,7 @@ ; ; CHECK-DAG: ![[FILE:[0-9]+]] = !DIFile(filename: "coro-debug.cpp" ; CHECK-DAG: ![[RAMP:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", -; CHECK-DAG: ![[RAMP_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[RAMP]], file: ![[FILE]], line: 23 -; CHECK-DAG: ![[CORO_FRAME]] = !DILocalVariable(name: "__coro_frame", scope: ![[RAMP_SCOPE]], file: ![[FILE]], line: [[PROMISE_VAR_LINE:[0-9]+]], type: ![[FRAME_TYPE:[0-9]+]], flags: DIFlagArtificial) +; CHECK-DAG: ![[CORO_FRAME]] = !DILocalVariable(name: "__coro_frame", scope: ![[RAMP]], file: ![[FILE]], line: [[CORO_FRAME_LINE:[0-9]+]], type: ![[FRAME_TYPE:[0-9]+]], flags: DIFlagArtificial) ; CHECK-DAG: ![[FRAME_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "f.coro_frame_ty", {{.*}}elements: ![[ELEMENTS:[0-9]+]] ; CHECK-DAG: ![[ELEMENTS]] = !{![[RESUME_FN:[0-9]+]], ![[DESTROY_FN:[0-9]+]], ![[PROMISE:[0-9]+]], ![[VECTOR_TYPE:[0-9]+]], ![[INT64_0:[0-9]+]], ![[DOUBLE_1:[0-9]+]], ![[INT64_PTR:[0-9]+]], ![[INT32_2:[0-9]+]], ![[INT32_3:[0-9]+]], ![[UNALIGNED_UNKNOWN:[0-9]+]], ![[STRUCT:[0-9]+]], ![[CORO_INDEX:[0-9]+]], ![[SMALL_UNKNOWN:[0-9]+]] ; CHECK-DAG: ![[RESUME_FN]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn"{{.*}}, baseType: ![[RESUME_FN_TYPE:[0-9]+]]{{.*}}, flags: DIFlagArtificial @@ -29,25 +28,26 @@ ; CHECK-DAG: ![[UNKNOWN_TYPE_BASE]] = !DIBasicType(name: "UnknownType", size: 8, encoding: DW_ATE_unsigned_char, flags: DIFlagArtificial) ; CHECK-DAG: ![[VECTOR_TYPE_BASE_ELEMENTS]] = !{![[VECTOR_TYPE_BASE_SUBRANGE:[0-9]+]]} ; CHECK-DAG: ![[VECTOR_TYPE_BASE_SUBRANGE]] = !DISubrange(count: 16, lowerBound: 0) -; CHECK-DAG: ![[INT64_0]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[PROMISE_VAR_LINE]], baseType: ![[I64_BASE:[0-9]+]],{{.*}}, flags: DIFlagArtificial +; CHECK-DAG: ![[INT64_0]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I64_BASE:[0-9]+]],{{.*}}, flags: DIFlagArtificial ; CHECK-DAG: ![[I64_BASE]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial) -; CHECK-DAG: ![[DOUBLE_1]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[PROMISE_VAR_LINE]], baseType: ![[DOUBLE_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial +; CHECK-DAG: ![[DOUBLE_1]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[DOUBLE_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial ; CHECK-DAG: ![[DOUBLE_BASE]] = !DIBasicType(name: "__double_", size: 64, encoding: DW_ATE_float, flags: DIFlagArtificial) -; CHECK-DAG: ![[INT32_2]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[PROMISE_VAR_LINE]], baseType: ![[I32_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial +; CHECK-DAG: ![[INT32_2]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial ; CHECK-DAG: ![[I32_BASE]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial) -; CHECK-DAG: ![[INT32_3]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_5", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[PROMISE_VAR_LINE]], baseType: ![[I32_BASE]] +; CHECK-DAG: ![[INT32_3]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_5", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE]] ; CHECK-DAG: ![[UNALIGNED_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "_6",{{.*}}baseType: ![[UNALIGNED_UNKNOWN_BASE:[0-9]+]], size: 9 ; CHECK-DAG: ![[UNALIGNED_UNKNOWN_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 16,{{.*}} elements: ![[UNALIGNED_UNKNOWN_ELEMENTS:[0-9]+]]) ; CHECK-DAG: ![[UNALIGNED_UNKNOWN_ELEMENTS]] = !{![[UNALIGNED_UNKNOWN_SUBRANGE:[0-9]+]]} ; CHECk-DAG: ![[UNALIGNED_UNKNOWN_SUBRANGE]] = !DISubrange(count: 2, lowerBound: 0) -; CHECK-DAG: ![[STRUCT]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_7", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[PROMISE_VAR_LINE]], baseType: ![[STRUCT_BASE:[0-9]+]] +; CHECK-DAG: ![[STRUCT]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_7", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[STRUCT_BASE:[0-9]+]] ; CHECK-DAG: ![[STRUCT_BASE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure"{{.*}}, align: 64, flags: DIFlagArtificial, elements: ![[STRUCT_ELEMENTS:[0-9]+]] ; CHECK-DAG: ![[STRUCT_ELEMENTS]] = !{![[MEM_TYPE:[0-9]+]]} ; CHECK-DAG: ![[MEM_TYPE]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[MEM_TYPE_BASE:[0-9]+]], size: 4000 ; CHECK-DAG: ![[MEM_TYPE_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 4000, ; CHECK-DAG: ![[CORO_INDEX]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index" ; CHECK-DAG: ![[SMALL_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "UnknownType_8",{{.*}} baseType: ![[UNKNOWN_TYPE_BASE]], size: 5 -; CHECK-DAG: ![[PROMISE_VAR:[0-9]+]] = !DILocalVariable(name: "__promise", scope: ![[RAMP_SCOPE]], file: ![[FILE]], line: [[PROMISE_VAR_LINE]] +; CHECK-DAG: ![[PROMISE_VAR:[0-9]+]] = !DILocalVariable(name: "__promise", scope: ![[RAMP_SCOPE:[0-9]+]], file: ![[FILE]] +; CHECK-DAG: ![[RAMP_SCOPE]] = distinct !DILexicalBlock(scope: ![[RAMP]], file: ![[FILE]], line: 23 ; CHECK-DAG: ![[BAR_FUNC:[0-9]+]] = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", ; CHECK-DAG: ![[BAR_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[BAR_FUNC]], file: !1 ; CHECK-DAG: ![[FRAME_TYPE_IN_BAR:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar.coro_frame_ty", file: ![[FILE]], line: [[BAR_LINE:[0-9]+]]{{.*}}elements: ![[ELEMENTS_IN_BAR:[0-9]+]] diff --git a/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll b/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll index 0b3acc30a1eee0..28f5841bb20af7 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll @@ -25,6 +25,7 @@ ; CHECK-SAME: ptr {{.*}} %[[frame:.*]]) ; CHECK-SAME: !dbg ![[RESUME_FN_DBG_NUM:[0-9]+]] ; CHECK: %[[frame_alloca:.*]] = alloca ptr +; CHECK-NEXT: #dbg_declare(ptr %begin.debug, ![[FRAME_DI_NUM:[0-9]+]], ; CHECK-NEXT: store ptr %[[frame]], ptr %[[frame_alloca]] ; CHECK: init.ready: ; CHECK: #dbg_value(ptr %[[frame_alloca]], ![[XVAR_RESUME:[0-9]+]], @@ -38,6 +39,7 @@ ; CHECK-SAME: !DIExpression(DW_OP_deref, DW_OP_plus_uconst, [[OffsetJ]], DW_OP_deref) ; ; CHECK: ![[RESUME_FN_DBG_NUM]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov" +; CHECK: ![[FRAME_DI_NUM]] = !DILocalVariable(name: "__coro_frame" ; CHECK: ![[IVAR_RESUME]] = !DILocalVariable(name: "i" ; CHECK: ![[XVAR_RESUME]] = !DILocalVariable(name: "x" ; CHECK: ![[JVAR_RESUME]] = !DILocalVariable(name: "j" diff --git a/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll index 4f5cdcf15618c7..93b22081cf12f6 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll @@ -42,12 +42,14 @@ ; CHECK-NEXT: %[[DBG_PTR:.*]] = alloca ptr ; CHECK-NEXT: #dbg_declare(ptr %[[DBG_PTR]], ![[XVAR_RESUME:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32), ; CHECK-NEXT: #dbg_declare(ptr %[[DBG_PTR]], ![[IVAR_RESUME:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 20), ![[IDBGLOC_RESUME:[0-9]+]] +; CHECK-NEXT: #dbg_declare(ptr %[[DBG_PTR]], ![[FRAME_RESUME:[0-9]+]], !DIExpression(DW_OP_deref), ; CHECK-NEXT: store ptr {{.*}}, ptr %[[DBG_PTR]] ; CHECK: %[[J:.*]] = alloca i32, align 4 ; CHECK-NEXT: #dbg_declare(ptr %[[J]], ![[JVAR_RESUME:[0-9]+]], !DIExpression(), ![[JDBGLOC_RESUME:[0-9]+]] ; CHECK: init.ready: ; CHECK: await.ready: ; +; CHECK-DAG: ![[FRAME_RESUME]] = !DILocalVariable(name: "__coro_frame" ; CHECK-DAG: ![[IVAR]] = !DILocalVariable(name: "i" ; CHECK-DAG: ![[PROG_SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov" ; CHECK-DAG: ![[BLK_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[PROG_SCOPE]], file: !1, line: 23, column: 12) diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll index 4432c4f3c541af..05c8bdaf66e7aa 100644 --- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll +++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll @@ -1079,15 +1079,12 @@ define internal void @control(ptr dereferenceable(4) %a) { define internal void @naked(ptr dereferenceable(4) %a) naked { ; FNATTRS-LABEL: define internal void @naked( ; FNATTRS-SAME: ptr dereferenceable(4) [[A:%.*]]) #[[ATTR10:[0-9]+]] { -; FNATTRS-NEXT: call void @use_i32_ptr(ptr [[A]]) ; FNATTRS-NEXT: ret void ; ; ATTRIBUTOR-LABEL: define internal void @naked( ; ATTRIBUTOR-SAME: ptr nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] { -; ATTRIBUTOR-NEXT: call void @use_i32_ptr(ptr [[A]]) ; ATTRIBUTOR-NEXT: ret void ; - call void @use_i32_ptr(ptr %a) ret void } ; Avoid nonnull as we do not touch optnone diff --git a/llvm/test/Verifier/naked.ll b/llvm/test/Verifier/naked.ll new file mode 100644 index 00000000000000..fc223858cf162e --- /dev/null +++ b/llvm/test/Verifier/naked.ll @@ -0,0 +1,8 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: cannot use argument of naked function +define void @test(ptr %ptr) naked { + getelementptr i8, ptr %ptr, i64 1 + call void @llvm.trap() + unreachable +} diff --git a/llvm/unittests/IR/DataLayoutTest.cpp b/llvm/unittests/IR/DataLayoutTest.cpp index 9464b489b65f43..396d44af19f53f 100644 --- a/llvm/unittests/IR/DataLayoutTest.cpp +++ b/llvm/unittests/IR/DataLayoutTest.cpp @@ -21,53 +21,130 @@ namespace { class DataLayoutTest : public ::testing::Test {}; -// TODO: Split into multiple TESTs. -TEST(DataLayoutTest, ParseErrors) { - EXPECT_THAT_EXPECTED( - DataLayout::parse("^"), - FailedWithMessage("Unknown specifier in datalayout string")); - EXPECT_THAT_EXPECTED( - DataLayout::parse("m:v"), - FailedWithMessage("Unknown mangling in datalayout string")); - EXPECT_THAT_EXPECTED( - DataLayout::parse("n0"), - FailedWithMessage("Zero width native integer type in datalayout string")); - EXPECT_THAT_EXPECTED( - DataLayout::parse("m"), - FailedWithMessage("Expected mangling specifier in datalayout string")); - EXPECT_THAT_EXPECTED( - DataLayout::parse("m."), - FailedWithMessage("Unexpected trailing characters after mangling " - "specifier in datalayout string")); +TEST(DataLayout, LayoutStringFormat) { + for (StringRef Str : {"", "e", "m:e", "m:e-e"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); + + for (StringRef Str : {"-", "e-", "-m:e", "m:e--e"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage("empty specification is not allowed")); +} + +TEST(DataLayoutTest, InvalidSpecifier) { + EXPECT_THAT_EXPECTED(DataLayout::parse("^"), + FailedWithMessage("unknown specifier '^'")); + EXPECT_THAT_EXPECTED(DataLayout::parse("I8:8"), + FailedWithMessage("unknown specifier 'I'")); + EXPECT_THAT_EXPECTED(DataLayout::parse("e-X"), + FailedWithMessage("unknown specifier 'X'")); + EXPECT_THAT_EXPECTED(DataLayout::parse("p0:32:32-64"), + FailedWithMessage("unknown specifier '6'")); +} + +TEST(DataLayoutTest, ParseEndianness) { + EXPECT_THAT_EXPECTED(DataLayout::parse("e"), Succeeded()); + EXPECT_THAT_EXPECTED(DataLayout::parse("E"), Succeeded()); + + for (StringRef Str : {"ee", "e0", "e:0", "E0:E", "El", "E:B"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage("malformed specification, must be just 'e' or 'E'")); +} + +TEST(DataLayoutTest, ParseMangling) { + for (StringRef Str : {"m:a", "m:e", "m:l", "m:m", "m:o", "m:w", "m:x"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); + + for (StringRef Str : {"m", "ms:m", "m:"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage( + "malformed specification, must be of the form \"m:\"")); + + for (StringRef Str : {"m:ms", "m:E", "m:0"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), + FailedWithMessage("unknown mangling mode")); +} + +TEST(DataLayoutTest, ParseStackNaturalAlign) { + for (StringRef Str : {"S8", "S32768"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); + EXPECT_THAT_EXPECTED( - DataLayout::parse(":32"), + DataLayout::parse("S"), FailedWithMessage( - "Expected token before separator in datalayout string")); - EXPECT_THAT_EXPECTED( - DataLayout::parse("A16777216"), - FailedWithMessage("Invalid address space, must be a 24-bit integer")); + "malformed specification, must be of the form \"S\"")); + + for (StringRef Str : {"SX", "S0x20", "S65536"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage("stack natural alignment must be a 16-bit integer")); + EXPECT_THAT_EXPECTED( - DataLayout::parse("G16777216"), - FailedWithMessage("Invalid address space, must be a 24-bit integer")); + DataLayout::parse("S0"), + FailedWithMessage("stack natural alignment must be non-zero")); + + for (StringRef Str : {"S1", "S7", "S24", "S65535"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage("stack natural alignment must be a power of two " + "times the byte width")); +} + +TEST(DataLayoutTest, ParseAddrSpace) { + for (StringRef Str : {"P0", "A0", "G0", "P1", "A1", "G1", "P16777215", + "A16777215", "G16777215"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); + + for (StringRef Str : {"P", "A", "G"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage(("malformed specification, must be of the form \"" + + Twine(Str.front()) + "
\"") + .str())); + + for (StringRef Str : {"Px", "A0x1", "G16777216"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage("address space must be a 24-bit integer")); +} + +TEST(DataLayoutTest, ParseFuncPtrSpec) { + for (StringRef Str : {"Fi8", "Fn16", "Fi32768", "Fn32768"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); + EXPECT_THAT_EXPECTED( - DataLayout::parse("P16777216"), - FailedWithMessage("Invalid address space, must be a 24-bit integer")); + DataLayout::parse("F"), + FailedWithMessage( + "malformed specification, must be of the form \"F\"")); + EXPECT_THAT_EXPECTED( - DataLayout::parse("Fi24"), - FailedWithMessage("Alignment is neither 0 nor a power of 2")); + DataLayout::parse("FN"), + FailedWithMessage("unknown function pointer alignment type 'N'")); EXPECT_THAT_EXPECTED( - DataLayout::parse("S24"), - FailedWithMessage("Alignment is neither 0 nor a power of 2")); -} + DataLayout::parse("F32"), + FailedWithMessage("unknown function pointer alignment type '3'")); -TEST(DataLayout, LayoutStringFormat) { - for (StringRef Str : {"", "e", "m:e", "m:e-e"}) - EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); + for (StringRef Str : {"Fi", "Fn"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage("ABI alignment component cannot be empty")); - for (StringRef Str : {"-", "e-", "-m:e", "m:e--e"}) + for (StringRef Str : {"Fii", "Fn32x", "Fi65536", "Fn65536"}) EXPECT_THAT_EXPECTED( DataLayout::parse(Str), - FailedWithMessage("empty specification is not allowed")); + FailedWithMessage("ABI alignment must be a 16-bit integer")); + + for (StringRef Str : {"Fi0", "Fn0"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), + FailedWithMessage("ABI alignment must be non-zero")); + + for (StringRef Str : {"Fi12", "Fn24"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage( + "ABI alignment must be a power of two times the byte width")); } class DataLayoutPrimitiveSpecificationTest @@ -326,6 +403,21 @@ TEST(DataLayout, ParsePointerSpec) { FailedWithMessage("index size cannot be larger than the pointer size")); } +TEST(DataLayoutTest, ParseNativeIntegersSpec) { + for (StringRef Str : {"n1", "n1:8", "n24:12:16777215"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); + + for (StringRef Str : {"n", "n1:", "n:8", "n16::32"}) + EXPECT_THAT_EXPECTED(DataLayout::parse(Str), + FailedWithMessage("size component cannot be empty")); + + for (StringRef Str : {"n0", "n0x8:16", "n8:0", "n16:0:32", "n16777216", + "n16:16777216", "n32:64:16777216"}) + EXPECT_THAT_EXPECTED( + DataLayout::parse(Str), + FailedWithMessage("size must be a non-zero 24-bit integer")); +} + TEST(DataLayout, ParseNonIntegralAddrSpace) { for (StringRef Str : {"ni:1", "ni:16777215", "ni:1:16777215"}) EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded()); @@ -494,12 +586,12 @@ TEST(DataLayoutTest, FunctionPtrAlign) { EXPECT_EQ(MaybeAlign(2), DataLayout("Fn16").getFunctionPtrAlign()); EXPECT_EQ(MaybeAlign(4), DataLayout("Fn32").getFunctionPtrAlign()); EXPECT_EQ(MaybeAlign(8), DataLayout("Fn64").getFunctionPtrAlign()); - EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \ - DataLayout("").getFunctionPtrAlignType()); - EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \ - DataLayout("Fi8").getFunctionPtrAlignType()); - EXPECT_EQ(DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign, \ - DataLayout("Fn8").getFunctionPtrAlignType()); + EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, + DataLayout("").getFunctionPtrAlignType()); + EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, + DataLayout("Fi8").getFunctionPtrAlignType()); + EXPECT_EQ(DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign, + DataLayout("Fn8").getFunctionPtrAlignType()); EXPECT_EQ(DataLayout("Fi8"), DataLayout("Fi8")); EXPECT_NE(DataLayout("Fi8"), DataLayout("Fi16")); EXPECT_NE(DataLayout("Fi8"), DataLayout("Fn8")); diff --git a/llvm/utils/git/github-automation.py b/llvm/utils/git/github-automation.py index 3e382548591c48..da467f46b4dd31 100755 --- a/llvm/utils/git/github-automation.py +++ b/llvm/utils/git/github-automation.py @@ -226,18 +226,13 @@ def run(self) -> bool: {PRGreeter.COMMENT_TAG} Thank you for submitting a Pull Request (PR) to the LLVM Project! -This PR will be automatically labeled and the relevant teams will be -notified. +This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. -If this is not working for you, it is probably because you do not have write -permissions for the repository. In which case you can instead tag reviewers by -name in a comment by using `@` followed by their GitHub username. +If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. -If you have received no comments on your PR for a week, you can request a review -by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate -is once a week. Please remember that you are asking for valuable time from other developers. +If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). @@ -281,18 +276,13 @@ def run(self) -> bool: {PRBuildbotInformation.COMMENT_TAG} @{self.author} Congratulations on having your first Pull Request (PR) merged into the LLVM Project! -Your changes will be combined with recent changes from other authors, then tested -by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may receive a report in an email or a comment on this PR. +Your changes will be combined with recent changes from other authors, then tested by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may receive a report in an email or a comment on this PR. -Please check whether problems have been caused by your change specifically, as -the builds can include changes from many authors. It is not uncommon for your -change to be included in a build that fails due to someone else's changes, or -infrastructure issues. +Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail [here](https://llvm.org/docs/MyFirstTypoFix.html#myfirsttypofix-issues-after-landing-your-pr). -If your change does cause a problem, it may be reverted, or you can revert it yourself. -This is a normal part of [LLVM development](https://llvm.org/docs/DeveloperPolicy.html#patch-reversion-policy). You can fix your changes and open a new PR to merge them again. +If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of [LLVM development](https://llvm.org/docs/DeveloperPolicy.html#patch-reversion-policy). You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! """ diff --git a/mlir/include/mlir/Analysis/SliceWalk.h b/mlir/include/mlir/Analysis/SliceWalk.h index 481c5690c533ba..eb9ced2ff63b68 100644 --- a/mlir/include/mlir/Analysis/SliceWalk.h +++ b/mlir/include/mlir/Analysis/SliceWalk.h @@ -88,9 +88,9 @@ WalkContinuation walkSlice(mlir::ValueRange rootValues, WalkCallback walkCallback); /// Computes a vector of all control predecessors of `value`. Relies on -/// RegionBranchOpInterface and BranchOpInterface to determine predecessors. -/// Returns nullopt if `value` has no predecessors or when the relevant -/// operations are missing the interface implementations. +/// RegionBranchOpInterface, BranchOpInterface, and SelectLikeOpInterface to +/// determine predecessors. Returns nullopt if `value` has no predecessors or +/// when the relevant operations are missing the interface implementations. std::optional> getControlFlowPredecessors(Value value); } // namespace mlir diff --git a/mlir/include/mlir/Dialect/Arith/IR/Arith.h b/mlir/include/mlir/Dialect/Arith/IR/Arith.h index 00cdb13feb29bb..77241319851e6c 100644 --- a/mlir/include/mlir/Dialect/Arith/IR/Arith.h +++ b/mlir/include/mlir/Dialect/Arith/IR/Arith.h @@ -14,6 +14,7 @@ #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" #include "mlir/Interfaces/CastInterfaces.h" +#include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/InferIntRangeInterface.h" #include "mlir/Interfaces/InferTypeOpInterface.h" #include "mlir/Interfaces/SideEffectInterfaces.h" diff --git a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td index 477478a4651cee..19a5e13a5d755d 100644 --- a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td +++ b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td @@ -12,6 +12,7 @@ include "mlir/Dialect/Arith/IR/ArithBase.td" include "mlir/Dialect/Arith/IR/ArithOpsInterfaces.td" include "mlir/Interfaces/CastInterfaces.td" +include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/InferIntRangeInterface.td" include "mlir/Interfaces/InferTypeOpInterface.td" include "mlir/Interfaces/SideEffectInterfaces.td" @@ -1578,6 +1579,7 @@ def SelectOp : Arith_Op<"select", [Pure, AllTypesMatch<["true_value", "false_value", "result"]>, BooleanConditionOrMatchingShape<"condition", "result">, DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods, ] # ElementwiseMappable.traits> { let summary = "select operation"; let description = [{ diff --git a/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td b/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td index 45efabf5fe1b43..699022b07e768a 100644 --- a/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td +++ b/mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td @@ -170,8 +170,8 @@ def OuterProductFusion Becomes: ```mlir - %a_packed = "llvm.intr.experimental.vector.interleave2"(%a0, %a1) : (vector<[4]xf16>, vector<[4]xf16>) -> vector<[8]xf16> - %b_packed = "llvm.intr.experimental.vector.interleave2"(%b0, %b1) : (vector<[4]xf16>, vector<[4]xf16>) -> vector<[8]xf16> + %a_packed = vector.interleave %a0, %a1 : vector<[4]xf16> -> vector<[8]xf16> + %b_packed = vector.interleave %b0, %b1 : vector<[4]xf16> -> vector<[8]xf16> %0 = arm_sme.fmopa_2way %a_packed, %b_packed : vector<[8]xf16>, vector<[8]xf16> into vector<[4]x[4]xf32> ``` diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td index 80cd13d687f5a6..95022d7d665d2d 100644 --- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td @@ -164,7 +164,7 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> { write. Counter-example: bufferization.alloc_tensor - The op just allocates and does not specifiy the data of the tensor, + The op just allocates and does not specify the data of the tensor, so resultBufferizesToMemoryWrite is overridden to return false. 2. At least one aliasing OpOperand bufferizes to a memory write. diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 643522d5903fd0..71f249fa538ca9 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -835,7 +835,8 @@ def LLVM_ShuffleVectorOp : LLVM_Op<"shufflevector", def LLVM_SelectOp : LLVM_Op<"select", [Pure, AllTypesMatch<["trueValue", "falseValue", "res"]>, - DeclareOpInterfaceMethods]>, + DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods]>, LLVM_Builder< "$res = builder.CreateSelect($condition, $trueValue, $falseValue);"> { let arguments = (ins LLVM_ScalarOrVectorOf:$condition, diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td index 61c5a7a6394f8a..ab535d7b2a304d 100644 --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td @@ -760,7 +760,8 @@ def SPIRV_SLessThanEqualOp : SPIRV_LogicalBinaryOp<"SLessThanEqual", def SPIRV_SelectOp : SPIRV_Op<"Select", [Pure, AllTypesMatch<["true_value", "false_value", "result"]>, - UsableInSpecConstantOp]> { + UsableInSpecConstantOp, + DeclareOpInterfaceMethods]> { let summary = [{ Select between two objects. Before version 1.4, results are only computed per component. diff --git a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td index 95ac5dea243aa4..69bce78e946c83 100644 --- a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td +++ b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td @@ -343,6 +343,38 @@ def RegionBranchTerminatorOpInterface : }]; } +def SelectLikeOpInterface : OpInterface<"SelectLikeOpInterface"> { + let description = [{ + This interface provides information for select-like operations, i.e., + operations that forward specific operands to the output, depending on a + binary condition. + + If the value of the condition is 1, then the `true` operand is returned, + and the third operand is ignored, even if it was poison. + + If the value of the condition is 0, then the `false` operand is returned, + and the second operand is ignored, even if it was poison. + + If the condition is poison, then poison is returned. + + Implementing operations can also accept shaped conditions, in which case + the operation works element-wise. + }]; + let cppNamespace = "::mlir"; + + let methods = [ + InterfaceMethod<[{ + Returns the operand that would be chosen for a false condition. + }], "::mlir::Value", "getFalseValue", (ins)>, + InterfaceMethod<[{ + Returns the operand that would be chosen for a true condition. + }], "::mlir::Value", "getTrueValue", (ins)>, + InterfaceMethod<[{ + Returns the condition operand. + }], "::mlir::Value", "getCondition", (ins)> + ]; +} + //===----------------------------------------------------------------------===// // ControlFlow Traits //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Analysis/SliceWalk.cpp b/mlir/lib/Analysis/SliceWalk.cpp index 9d770639dc53ca..817d71a3452caf 100644 --- a/mlir/lib/Analysis/SliceWalk.cpp +++ b/mlir/lib/Analysis/SliceWalk.cpp @@ -104,9 +104,11 @@ getBlockPredecessorOperands(BlockArgument blockArg) { std::optional> mlir::getControlFlowPredecessors(Value value) { - SmallVector result; if (OpResult opResult = dyn_cast(value)) { - auto regionOp = dyn_cast(opResult.getOwner()); + if (auto selectOp = opResult.getDefiningOp()) + return SmallVector( + {selectOp.getTrueValue(), selectOp.getFalseValue()}); + auto regionOp = opResult.getDefiningOp(); // If the interface is not implemented, there are no control flow // predecessors to work with. if (!regionOp) diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp index 1399d419735db9..031930dcfc2131 100644 --- a/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp +++ b/mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp @@ -235,11 +235,6 @@ getUnderlyingObjectSet(Value pointerValue) { if (auto addrCast = val.getDefiningOp()) return WalkContinuation::advanceTo(addrCast.getOperand()); - // TODO: Add a SelectLikeOpInterface and use it in the slicing utility. - if (auto selectOp = val.getDefiningOp()) - return WalkContinuation::advanceTo( - {selectOp.getTrueValue(), selectOp.getFalseValue()}); - // Attempt to advance to control flow predecessors. std::optional> controlFlowPredecessors = getControlFlowPredecessors(val); diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp index 392f552f480cc8..35001757f214e1 100644 --- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp +++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp @@ -197,9 +197,9 @@ DataLayoutImporter::tryToEmplaceStackAlignmentEntry(StringRef token) { if (failed(alignment)) return failure(); - // Only store the stack alignment if it has a non-default value. + // Stack alignment shouldn't be zero. if (*alignment == 0) - return success(); + return failure(); OpBuilder builder(context); keyEntries.try_emplace(key, DataLayoutEntryAttr::get( key, builder.getI64IntegerAttr(*alignment))); diff --git a/mlir/python/mlir/extras/__init__.py b/mlir/python/mlir/extras/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir index 89dafa7529ed53..836d8aedefc1f0 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir @@ -43,3 +43,19 @@ func.func @zero_rank() { // expected-error@+1 {{failed to legalize operation 'memref.global'}} memref.global "nested" constant @nested_global : memref<3x7xf32> + +// ----- + +func.func @unsupported_type_f16() { + // expected-error@+1 {{failed to legalize operation 'memref.alloca'}} + %0 = memref.alloca() : memref<4xf16> + return +} + +// ----- + +func.func @unsupported_type_i4() { + // expected-error@+1 {{failed to legalize operation 'memref.alloca'}} + %0 = memref.alloca() : memref<4xi4> + return +} diff --git a/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir b/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir index bd5e7aa996ada7..6b369c50121050 100644 --- a/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir +++ b/mlir/test/Dialect/LLVMIR/inlining-alias-scopes.mlir @@ -508,3 +508,51 @@ llvm.func @noalias_with_region(%arg0: !llvm.ptr) { llvm.call @region(%arg0) : (!llvm.ptr) -> () llvm.return } + +// ----- + +// CHECK-DAG: #[[DOMAIN:.*]] = #llvm.alias_scope_domain<{{.*}}> +// CHECK-DAG: #[[$ARG_SCOPE:.*]] = #llvm.alias_scope + +llvm.func @foo(%arg: i32) + +llvm.func @func(%arg0: !llvm.ptr {llvm.noalias}, %arg1: !llvm.ptr) { + %cond = llvm.load %arg1 : !llvm.ptr -> i1 + %1 = llvm.getelementptr inbounds %arg0[1] : (!llvm.ptr) -> !llvm.ptr, f32 + %selected = llvm.select %cond, %arg0, %1 : i1, !llvm.ptr + %2 = llvm.load %selected : !llvm.ptr -> i32 + llvm.call @foo(%2) : (i32) -> () + llvm.return +} + +// CHECK-LABEL: llvm.func @selects +// CHECK: llvm.load +// CHECK-NOT: alias_scopes +// CHECK-SAME: noalias_scopes = [#[[$ARG_SCOPE]]] +// CHECK: llvm.load +// CHECK-SAME: alias_scopes = [#[[$ARG_SCOPE]]] +llvm.func @selects(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { + llvm.call @func(%arg0, %arg1) : (!llvm.ptr, !llvm.ptr) -> () + llvm.return +} + +// ----- + +llvm.func @foo(%arg: i32) + +llvm.func @func(%cond: i1, %arg0: !llvm.ptr {llvm.noalias}, %arg1: !llvm.ptr) { + %selected = llvm.select %cond, %arg0, %arg1 : i1, !llvm.ptr + %2 = llvm.load %selected : !llvm.ptr -> i32 + llvm.call @foo(%2) : (i32) -> () + llvm.return +} + +// CHECK-LABEL: llvm.func @multi_ptr_select +// CHECK: llvm.load +// CHECK-NOT: alias_scopes +// CHECK-NOT: noalias_scopes +// CHECK: llvm.call @foo +llvm.func @multi_ptr_select(%cond: i1, %arg0: !llvm.ptr, %arg1: !llvm.ptr) { + llvm.call @func(%cond, %arg0, %arg1) : (i1, !llvm.ptr, !llvm.ptr) -> () + llvm.return +} diff --git a/mlir/test/Target/LLVMIR/Import/data-layout.ll b/mlir/test/Target/LLVMIR/Import/data-layout.ll index de90ac1e271140..ee6f4dd994f1d0 100644 --- a/mlir/test/Target/LLVMIR/Import/data-layout.ll +++ b/mlir/test/Target/LLVMIR/Import/data-layout.ll @@ -47,5 +47,4 @@ target datalayout = "A1-E-p270:16:32:64:8-p271:16:32:64-i64:64:128" ; CHECK: dlti.dl_spec = ; CHECK: #dlti.dl_spec< ; CHECK-NOT: #dlti.dl_entry<"dlti.alloca_memory_space" -; CHECK-NOT: #dlti.dl_entry<"dlti.stack_alignment" -target datalayout = "A0-S0" +target datalayout = "A0"