Skip to content

Commit

Permalink
merge main into amd-staging
Browse files Browse the repository at this point in the history
Change-Id: I49b08a1848ec2f1046265cd0b9c8a0574000fcb5
  • Loading branch information
Jenkins authored and ronlieb committed Dec 8, 2024
2 parents db5d3ba + b6dfdd2 commit 2feaf93
Show file tree
Hide file tree
Showing 40 changed files with 563 additions and 148 deletions.
5 changes: 4 additions & 1 deletion clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,10 @@ A **partial** list of flags RealtimeSanitizer respects:
- ``""``
- path
- If set to a valid suppressions file, will suppress issue reporting. See details in `Disabling and Suppressing`_.

* - ``verify_interceptors``
- ``true``
- boolean
- If true, verifies interceptors are working at initialization. The program will abort with error ``==ERROR: Interceptors are not working. This may be because RealtimeSanitizer is loaded too late (e.g. via dlopen)`` if an issue is detected.

Some issues with flags can be debugged using the ``verbosity=$NUM`` flag:

Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/arm_sve.td
Original file line number Diff line number Diff line change
Expand Up @@ -2429,6 +2429,10 @@ let SVETargetGuard = InvalidMode, SMETargetGuard = "sme2,fp8" in {
def FSCALE_X2 : Inst<"svscale[_{d}_x2]", "222.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x2", [IsStreaming],[]>;
def FSCALE_X4 : Inst<"svscale[_{d}_x4]", "444.x", "fhd", MergeNone, "aarch64_sme_fp8_scale_x4", [IsStreaming],[]>;

// Convert from FP8 to half-precision/BFloat16 multi-vector
def SVF1CVT : Inst<"svcvt1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt1_x2", [IsStreaming, SetsFPMR], []>;
def SVF2CVT : Inst<"svcvt2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvt2_x2", [IsStreaming, SetsFPMR], []>;

// Convert from FP8 to deinterleaved half-precision/BFloat16 multi-vector
def SVF1CVTL : Inst<"svcvtl1_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl1_x2", [IsStreaming, SetsFPMR], []>;
def SVF2CVTL : Inst<"svcvtl2_{d}[_mf8]_x2_fpm", "2~>", "bh", MergeNone, "aarch64_sve_fp8_cvtl2_x2", [IsStreaming, SetsFPMR], []>;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/BitcastBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct Bits {
bool operator>=(Bits Other) const { return N >= Other.N; }
bool operator<=(Bits Other) const { return N <= Other.N; }
bool operator==(Bits Other) const { return N == Other.N; }
bool operator!=(Bits Other) const { return N != Other.N; }
};

/// A quantity in bytes.
Expand Down
23 changes: 12 additions & 11 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LLVM_CLANG_AST_INTERP_INTERP_H

#include "../ExprConstShared.h"
#include "BitcastBuffer.h"
#include "Boolean.h"
#include "DynamicAllocator.h"
#include "FixedPoint.h"
Expand Down Expand Up @@ -3050,24 +3051,24 @@ inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
llvm::SmallVector<std::byte> Buff(BuffSize);
bool HasIndeterminateBits = false;

if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BuffSize, HasIndeterminateBits))
Bits FullBitWidth(ResultBitWidth);
Bits BitWidth = FullBitWidth;

if constexpr (std::is_same_v<T, Floating>) {
assert(Sem);
BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
}

if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
HasIndeterminateBits))
return false;

if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
return false;

if constexpr (std::is_same_v<T, Floating>) {
assert(Sem);
ptrdiff_t Offset = 0;

if (llvm::sys::IsBigEndianHost) {
unsigned NumBits = llvm::APFloatBase::getSizeInBits(*Sem);
assert(NumBits % 8 == 0);
assert(NumBits <= ResultBitWidth);
Offset = (ResultBitWidth - NumBits) / 8;
}

S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data() + Offset, *Sem));
S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
} else {
assert(!Sem);
S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
Expand Down
19 changes: 12 additions & 7 deletions clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,44 +278,49 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
if (llvm::sys::IsBigEndianHost)
swapBytes(Buff.get(), NumBits.roundToBytes());

Buffer.markInitialized(BitOffset, NumBits);
} else {
BITCAST_TYPE_SWITCH(T, { P.deref<T>().bitcastToMemory(Buff.get()); });

if (llvm::sys::IsBigEndianHost)
swapBytes(Buff.get(), FullBitWidth.roundToBytes());
Buffer.markInitialized(BitOffset, BitWidth);
}

Buffer.pushData(Buff.get(), BitOffset, BitWidth, TargetEndianness);
Buffer.markInitialized(BitOffset, BitWidth);
return true;
});
}

bool clang::interp::DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
std::byte *Buff, size_t BuffSize,
std::byte *Buff, Bits BitWidth, Bits FullBitWidth,
bool &HasIndeterminateBits) {
assert(Ptr.isLive());
assert(Ptr.isBlockPointer());
assert(Buff);
assert(BitWidth <= FullBitWidth);
assert(FullBitWidth.isFullByte());
assert(BitWidth.isFullByte());

Bits BitSize = Bytes(BuffSize).toBits();
BitcastBuffer Buffer(BitSize);
BitcastBuffer Buffer(FullBitWidth);
size_t BuffSize = FullBitWidth.roundToBytes();
if (!CheckBitcastType(S, OpPC, Ptr.getType(), /*IsToType=*/false))
return false;

bool Success = readPointerToBuffer(S.getContext(), Ptr, Buffer,
/*ReturnOnUninit=*/false);
HasIndeterminateBits = !Buffer.allInitialized();
HasIndeterminateBits = !Buffer.rangeInitialized(Bits::zero(), BitWidth);

const ASTContext &ASTCtx = S.getASTContext();
Endian TargetEndianness =
ASTCtx.getTargetInfo().isLittleEndian() ? Endian::Little : Endian::Big;
auto B = Buffer.copyBits(Bits::zero(), BitSize, BitSize, TargetEndianness);
auto B =
Buffer.copyBits(Bits::zero(), BitWidth, FullBitWidth, TargetEndianness);

std::memcpy(Buff, B.get(), BuffSize);

if (llvm::sys::IsBigEndianHost)
swapBytes(Buff, BuffSize);
swapBytes(Buff, BitWidth.roundToBytes());

return Success;
}
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/ByteCode/InterpBuiltinBitCast.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_AST_INTERP_BUILITN_BIT_CAST_H
#define LLVM_CLANG_AST_INTERP_BUILITN_BIT_CAST_H

#include "BitcastBuffer.h"
#include <cstddef>

namespace clang {
Expand All @@ -18,7 +19,8 @@ class InterpState;
class CodePtr;

bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
std::byte *Buff, size_t BuffSize, bool &HasIndeterminateBits);
std::byte *Buff, Bits BitWidth, Bits FullBitWidth,
bool &HasIndeterminateBits);
bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr,
Pointer &ToPtr);
bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr,
Expand Down
19 changes: 14 additions & 5 deletions clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter

#if !__x86_64
// both-no-diagnostics
#endif


typedef decltype(nullptr) nullptr_t;
typedef __INTPTR_TYPE__ intptr_t;
Expand Down Expand Up @@ -35,6 +38,7 @@ constexpr Init round_trip(const Init &init) {

namespace test_long_double {
#if __x86_64
/// FIXME: We could enable this, but since it aborts, it causes the usual mempory leak.
#if 0
constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\
// expected-note{{in call}}
Expand All @@ -49,7 +53,13 @@ static_assert(round_trip<bytes>(ld), "");

static_assert(round_trip<long double>(10.0L));

#if 0
constexpr long double foo() {
bytes A = __builtin_bit_cast(bytes, ld);
long double ld = __builtin_bit_cast(long double, A);
return ld;
}
static_assert(foo() == ld);

constexpr bool f(bool read_uninit) {
bytes b = bit_cast<bytes>(ld);
unsigned char ld_bytes[10] = {
Expand All @@ -61,16 +71,15 @@ constexpr bool f(bool read_uninit) {
if (ld_bytes[i] != b.d[i])
return false;

if (read_uninit && b.d[10]) // expected-note{{read of uninitialized object is not allowed in a constant expression}}
if (read_uninit && b.d[10]) // both-note{{read of uninitialized object is not allowed in a constant expression}}
return false;

return true;
}

static_assert(f(/*read_uninit=*/false), "");
static_assert(f(/*read_uninit=*/true), ""); // expected-error{{static assertion expression is not an integral constant expression}} \
// expected-note{{in call to 'f(true)'}}
#endif
static_assert(f(/*read_uninit=*/true), ""); // both-error{{static assertion expression is not an integral constant expression}} \
// both-note{{in call to 'f(true)'}}
constexpr bytes ld539 = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xc0, 0x86,
Expand Down
64 changes: 64 additions & 0 deletions clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_cvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,70 @@
#define SVE_ACLE_FUNC(A1,A2,A3) A1##A2##A3
#endif

// CHECK-LABEL: @test_cvt1_f16_x2(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x half>, <vscale x 8 x half> } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8f16(<vscale x 16 x i8> [[ZN:%.*]])
// CHECK-NEXT: ret { <vscale x 8 x half>, <vscale x 8 x half> } [[TMP0]]
//
// CPP-CHECK-LABEL: @_Z16test_cvt1_f16_x2u13__SVMfloat8_tm(
// CPP-CHECK-NEXT: entry:
// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x half>, <vscale x 8 x half> } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8f16(<vscale x 16 x i8> [[ZN:%.*]])
// CPP-CHECK-NEXT: ret { <vscale x 8 x half>, <vscale x 8 x half> } [[TMP0]]
//
svfloat16x2_t test_cvt1_f16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming {
return SVE_ACLE_FUNC(svcvt1_f16,_mf8,_x2_fpm)(zn, fpmr);
}

// CHECK-LABEL: @test_cvt2_f16_x2(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x half>, <vscale x 8 x half> } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8f16(<vscale x 16 x i8> [[ZN:%.*]])
// CHECK-NEXT: ret { <vscale x 8 x half>, <vscale x 8 x half> } [[TMP0]]
//
// CPP-CHECK-LABEL: @_Z16test_cvt2_f16_x2u13__SVMfloat8_tm(
// CPP-CHECK-NEXT: entry:
// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x half>, <vscale x 8 x half> } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8f16(<vscale x 16 x i8> [[ZN:%.*]])
// CPP-CHECK-NEXT: ret { <vscale x 8 x half>, <vscale x 8 x half> } [[TMP0]]
//
svfloat16x2_t test_cvt2_f16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming {
return SVE_ACLE_FUNC(svcvt2_f16,_mf8,_x2_fpm)(zn, fpmr);
}

// CHECK-LABEL: @test_cvt1_bf16_x2(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8bf16(<vscale x 16 x i8> [[ZN:%.*]])
// CHECK-NEXT: ret { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } [[TMP0]]
//
// CPP-CHECK-LABEL: @_Z17test_cvt1_bf16_x2u13__SVMfloat8_tm(
// CPP-CHECK-NEXT: entry:
// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } @llvm.aarch64.sve.fp8.cvt1.x2.nxv8bf16(<vscale x 16 x i8> [[ZN:%.*]])
// CPP-CHECK-NEXT: ret { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } [[TMP0]]
//
svbfloat16x2_t test_cvt1_bf16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming {
return SVE_ACLE_FUNC(svcvt1_bf16,_mf8,_x2_fpm)(zn, fpmr);
}

// CHECK-LABEL: @test_cvt2_bf16_x2(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8bf16(<vscale x 16 x i8> [[ZN:%.*]])
// CHECK-NEXT: ret { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } [[TMP0]]
//
// CPP-CHECK-LABEL: @_Z17test_cvt2_bf16_x2u13__SVMfloat8_tm(
// CPP-CHECK-NEXT: entry:
// CPP-CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } @llvm.aarch64.sve.fp8.cvt2.x2.nxv8bf16(<vscale x 16 x i8> [[ZN:%.*]])
// CPP-CHECK-NEXT: ret { <vscale x 8 x bfloat>, <vscale x 8 x bfloat> } [[TMP0]]
//
svbfloat16x2_t test_cvt2_bf16_x2(svmfloat8_t zn, fpm_t fpmr) __arm_streaming {
return SVE_ACLE_FUNC(svcvt2_bf16,_mf8,_x2_fpm)(zn, fpmr);
}

// CHECK-LABEL: @test_cvtl1_f16_x2(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.aarch64.set.fpmr(i64 [[FPMR:%.*]])
Expand Down
9 changes: 9 additions & 0 deletions clang/test/Sema/aarch64-fp8-intrinsics/acle_sme2_fp8_cvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ void test_features_sme2_fp8(svmfloat8_t zn, fpm_t fpmr) __arm_streaming {
svcvtl1_bf16_mf8_x2_fpm(zn, fpmr);
// expected-error@+1 {{'svcvtl2_bf16_mf8_x2_fpm' needs target feature sme,sme2,fp8}}
svcvtl2_bf16_mf8_x2_fpm(zn, fpmr);

// expected-error@+1 {{'svcvt1_f16_mf8_x2_fpm' needs target feature sme,sme2,fp8}}
svcvt1_f16_mf8_x2_fpm(zn, fpmr);
// expected-error@+1 {{'svcvt2_f16_mf8_x2_fpm' needs target feature sme,sme2,fp8}}
svcvt2_f16_mf8_x2_fpm(zn, fpmr);
// expected-error@+1 {{'svcvt1_bf16_mf8_x2_fpm' needs target feature sme,sme2,fp8}}
svcvt1_bf16_mf8_x2_fpm(zn, fpmr);
// expected-error@+1 {{'svcvt2_bf16_mf8_x2_fpm' needs target feature sme,sme2,fp8}}
svcvt2_bf16_mf8_x2_fpm(zn, fpmr);
}
26 changes: 24 additions & 2 deletions compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,14 +244,29 @@ INTERCEPTOR(FILE *, fopen, const char *path, const char *mode) {
return REAL(fopen)(path, mode);
}

INTERCEPTOR(FILE *, freopen, const char *path, const char *mode, FILE *stream) {
__rtsan_notify_intercepted_call("freopen");
return REAL(freopen)(path, mode, stream);
}

// Streams

#if SANITIZER_INTERCEPT_FOPEN64
INTERCEPTOR(FILE *, fopen64, const char *path, const char *mode) {
__rtsan_notify_intercepted_call("fopen64");
return REAL(fopen64)(path, mode);
}
#define RTSAN_MAYBE_INTERCEPT_FOPEN64 INTERCEPT_FUNCTION(fopen64)

INTERCEPTOR(FILE *, freopen64, const char *path, const char *mode,
FILE *stream) {
__rtsan_notify_intercepted_call("freopen64");
return REAL(freopen64)(path, mode, stream);
}
#define RTSAN_MAYBE_INTERCEPT_FOPEN64 INTERCEPT_FUNCTION(fopen64);
#define RTSAN_MAYBE_INTERCEPT_FREOPEN64 INTERCEPT_FUNCTION(freopen64);
#else
#define RTSAN_MAYBE_INTERCEPT_FOPEN64
#define RTSAN_MAYBE_INTERCEPT_FREOPEN64
#endif // SANITIZER_INTERCEPT_FOPEN64

INTERCEPTOR(size_t, fread, void *ptr, size_t size, size_t nitems,
Expand All @@ -276,7 +291,11 @@ INTERCEPTOR(int, fputs, const char *s, FILE *stream) {
return REAL(fputs)(s, stream);
}

// Streams
INTERCEPTOR(FILE *, fdopen, int fd, const char *mode) {
__rtsan_notify_intercepted_call("fdopen");
return REAL(fdopen)(fd, mode);
}

INTERCEPTOR(int, puts, const char *s) {
__rtsan_notify_intercepted_call("puts");
return REAL(puts)(s);
Expand Down Expand Up @@ -904,6 +923,7 @@ void __rtsan::InitializeInterceptors() {
INTERCEPT_FUNCTION(close);
INTERCEPT_FUNCTION(fopen);
RTSAN_MAYBE_INTERCEPT_FOPEN64;
RTSAN_MAYBE_INTERCEPT_FREOPEN64;
INTERCEPT_FUNCTION(fread);
INTERCEPT_FUNCTION(read);
INTERCEPT_FUNCTION(write);
Expand All @@ -921,6 +941,8 @@ void __rtsan::InitializeInterceptors() {
RTSAN_MAYBE_INTERCEPT_CREAT64;
INTERCEPT_FUNCTION(puts);
INTERCEPT_FUNCTION(fputs);
INTERCEPT_FUNCTION(fdopen);
INTERCEPT_FUNCTION(freopen);
INTERCEPT_FUNCTION(lseek);
RTSAN_MAYBE_INTERCEPT_LSEEK64;
INTERCEPT_FUNCTION(dup);
Expand Down
20 changes: 20 additions & 0 deletions compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,26 @@ TEST_F(RtsanOpenedFileTest, IoctlBehavesWithOutputArg) {
EXPECT_THAT(arg, Ge(0));
}

TEST_F(RtsanOpenedFileTest, FdopenDiesWhenRealtime) {
auto Func = [&]() {
FILE *f = fdopen(GetOpenFd(), "w");
EXPECT_THAT(f, Ne(nullptr));
};

ExpectRealtimeDeath(Func, "fdopen");
ExpectNonRealtimeSurvival(Func);
}

TEST_F(RtsanOpenedFileTest, FreopenDiesWhenRealtime) {
auto Func = [&]() {
FILE *newfile = freopen(GetTemporaryFilePath(), "w", GetOpenFile());
EXPECT_THAT(newfile, Ne(nullptr));
};

ExpectRealtimeDeath(Func, MAYBE_APPEND_64("freopen"));
ExpectNonRealtimeSurvival(Func);
}

TEST(TestRtsanInterceptors, IoctlBehavesWithOutputPointer) {
// These initial checks just see if we CAN run these tests.
// If we can't (can't open a socket, or can't find an interface, just
Expand Down
7 changes: 5 additions & 2 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1742,8 +1742,11 @@ static void createBitcodeSymbol(Ctx &ctx, Symbol *&sym,
} else {
Defined newSym(ctx, &f, StringRef(), binding, visibility, type, 0, 0,
nullptr);
if (objSym.canBeOmittedFromSymbolTable())
newSym.exportDynamic = false;
// The definition can be omitted if all bitcode definitions satisfy
// `canBeOmittedFromSymbolTable()` and isUsedInRegularObj is false.
// The latter condition is tested in Symbol::includeInDynsym.
sym->ltoCanOmit = objSym.canBeOmittedFromSymbolTable() &&
(!sym->isDefined() || sym->ltoCanOmit);
sym->resolve(ctx, newSym);
}
}
Expand Down
Loading

0 comments on commit 2feaf93

Please sign in to comment.