Skip to content

Commit

Permalink
Merged master:c10248829357 into amd-gfx:c6d4fa64b723
Browse files Browse the repository at this point in the history
Local branch amd-gfx c6d4fa6 Merged master:297655c123b3 into amd-gfx:774f38e38f9d
Remote branch master c102488 Add test for disabling Dead Virtual Function Elimination
  • Loading branch information
Sw authored and Sw committed Oct 7, 2020
2 parents c6d4fa6 + c102488 commit 6f010c8
Show file tree
Hide file tree
Showing 28 changed files with 272 additions and 187 deletions.
23 changes: 22 additions & 1 deletion clang/test/CodeGenCXX/virtual-function-elimination.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux -flto -flto-unit -fvirtual-function-elimination -fwhole-program-vtables -emit-llvm -o - %s | FileCheck %s

// RUN: %clang -target x86_64-unknown-linux -flto -fvirtual-function-elimination -fno-virtual-function-elimination -fwhole-program-vtables -S -emit-llvm -o - %s | FileCheck %s -check-prefix=NOVFE

struct __attribute__((visibility("default"))) A {
virtual void foo();
Expand All @@ -8,9 +8,13 @@ struct __attribute__((visibility("default"))) A {
void test_1(A *p) {
// A has default visibility, so no need for type.checked.load.
// CHECK-LABEL: define void @_Z6test_1P1A
// NOVFE-LABEL: define dso_local void @_Z6test_1P1A
// CHECK: [[FN_PTR_ADDR:%.+]] = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** {{%.+}}, i64 0
// NOVFE: [[FN_PTR_ADDR:%.+]] = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** {{%.+}}, i64 0
// CHECK: [[FN_PTR:%.+]] = load void (%struct.A*)*, void (%struct.A*)** [[FN_PTR_ADDR]]
// NOVFE: [[FN_PTR:%.+]] = load void (%struct.A*)*, void (%struct.A*)** [[FN_PTR_ADDR]]
// CHECK: call void [[FN_PTR]](
// NOVFE: call void [[FN_PTR]](
p->foo();
}

Expand All @@ -22,9 +26,13 @@ struct __attribute__((visibility("hidden"))) [[clang::lto_visibility_public]] B
void test_2(B *p) {
// B has public LTO visibility, so no need for type.checked.load.
// CHECK-LABEL: define void @_Z6test_2P1B
// NOVFE-LABEL: define dso_local void @_Z6test_2P1B
// CHECK: [[FN_PTR_ADDR:%.+]] = getelementptr inbounds void (%struct.B*)*, void (%struct.B*)** {{%.+}}, i64 0
// NOVFE: [[FN_PTR_ADDR:%.+]] = getelementptr inbounds void (%struct.B*)*, void (%struct.B*)** {{%.+}}, i64 0
// CHECK: [[FN_PTR:%.+]] = load void (%struct.B*)*, void (%struct.B*)** [[FN_PTR_ADDR]]
// NOVFE: [[FN_PTR:%.+]] = load void (%struct.B*)*, void (%struct.B*)** [[FN_PTR_ADDR]]
// CHECK: call void [[FN_PTR]](
// NOVFE: call void [[FN_PTR]](
p->foo();
}

Expand All @@ -37,21 +45,29 @@ struct __attribute__((visibility("hidden"))) C {
void test_3(C *p) {
// C has hidden visibility, so we generate type.checked.load to allow VFE.
// CHECK-LABEL: define void @_Z6test_3P1C
// NOVFE-LABEL: define dso_local void @_Z6test_3P1C
// CHECK: [[LOAD:%.+]] = call { i8*, i1 } @llvm.type.checked.load(i8* {{%.+}}, i32 0, metadata !"_ZTS1C")
// NOVFE: call i1 @llvm.type.test(i8* {{%.+}}, metadata !"_ZTS1C")
// CHECK: [[FN_PTR_I8:%.+]] = extractvalue { i8*, i1 } [[LOAD]], 0
// NOVFE: [[FN_PTR:%.+]] = load void (%struct.C*)*, void (%struct.C*)** {{%.+}}, align 8
// CHECK: [[FN_PTR:%.+]] = bitcast i8* [[FN_PTR_I8]] to void (%struct.C*)*
// CHECK: call void [[FN_PTR]](
// NOVFE: call void [[FN_PTR]](
p->foo();
}

void test_4(C *p) {
// When using type.checked.load, we pass the vtable offset to the intrinsic,
// rather than adding it to the pointer with a GEP.
// CHECK-LABEL: define void @_Z6test_4P1C
// NOVFE-LABEL: define dso_local void @_Z6test_4P1C
// CHECK: [[LOAD:%.+]] = call { i8*, i1 } @llvm.type.checked.load(i8* {{%.+}}, i32 8, metadata !"_ZTS1C")
// NOVFE: call i1 @llvm.type.test(i8* {{%.+}}, metadata !"_ZTS1C")
// CHECK: [[FN_PTR_I8:%.+]] = extractvalue { i8*, i1 } [[LOAD]], 0
// NOVFE: [[FN_PTR:%.+]] = load void (%struct.C*)*, void (%struct.C*)** {{%.+}}, align 8
// CHECK: [[FN_PTR:%.+]] = bitcast i8* [[FN_PTR_I8]] to void (%struct.C*)*
// CHECK: call void [[FN_PTR]](
// NOVFE: call void [[FN_PTR]](
p->bar();
}

Expand All @@ -64,12 +80,17 @@ void test_5(C *p, void (C::*q)(void)) {
// function pointer to the intrinsic, this information would be lost. No
// codegen changes on the non-virtual side.
// CHECK-LABEL: define void @_Z6test_5P1CMS_FvvE(
// NOVFE-LABEL: define dso_local void @_Z6test_5P1CMS_FvvE(
// CHECK: [[FN_PTR_ADDR:%.+]] = getelementptr i8, i8* %vtable, i64 {{%.+}}
// CHECK: [[LOAD:%.+]] = call { i8*, i1 } @llvm.type.checked.load(i8* [[FN_PTR_ADDR]], i32 0, metadata !"_ZTSM1CFvvE.virtual")
// NOVFE-NOT: call { i8*, i1 } @llvm.type.checked.load(i8* {{%.+}}, i32 0, metadata !"_ZTSM1CFvvE.virtual")
// CHECK: [[FN_PTR_I8:%.+]] = extractvalue { i8*, i1 } [[LOAD]], 0
// CHECK: [[FN_PTR:%.+]] = bitcast i8* [[FN_PTR_I8]] to void (%struct.C*)*
// NOVFE: [[FN_PTR:%.+]] = load void (%struct.C*)*, void (%struct.C*)** {{%.+}}, align 8

// CHECK: [[PHI:%.+]] = phi void (%struct.C*)* {{.*}}[ [[FN_PTR]], {{.*}} ]
// NOVFE: [[PHI:%.+]] = phi void (%struct.C*)* {{.*}}[ [[FN_PTR]], {{.*}} ]
// CHECK: call void [[PHI]](
// NOVFE: call void [[PHI]](
(p->*q)();
}
2 changes: 1 addition & 1 deletion compiler-rt/lib/hwasan/hwasan_report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ static void PrintStackAllocations(StackAllocationsRingBuffer *sa,
frame_desc.append(" record_addr:0x%zx record:0x%zx",
reinterpret_cast<uptr>(record_addr), record);
if (SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc)) {
RenderFrame(&frame_desc, " %F %L\n", 0, frame->info,
RenderFrame(&frame_desc, " %F %L\n", 0, frame->info.address, &frame->info,
common_flags()->symbolize_vs_style,
common_flags()->strip_path_prefix);
frame->ClearAll();
Expand Down
20 changes: 16 additions & 4 deletions compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,23 @@ void StackTrace::Print() const {
InternalScopedString frame_desc(GetPageSizeCached() * 2);
InternalScopedString dedup_token(GetPageSizeCached());
int dedup_frames = common_flags()->dedup_token_length;
bool symbolize = RenderNeedsSymbolization(common_flags()->stack_trace_format);
uptr frame_num = 0;
for (uptr i = 0; i < size && trace[i]; i++) {
// PCs in stack traces are actually the return addresses, that is,
// addresses of the next instructions after the call.
uptr pc = GetPreviousInstructionPc(trace[i]);
SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(pc);
SymbolizedStack *frames;
if (symbolize)
frames = Symbolizer::GetOrInit()->SymbolizePC(pc);
else
frames = SymbolizedStack::New(pc);
CHECK(frames);
for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
frame_desc.clear();
RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++,
cur->info, common_flags()->symbolize_vs_style,
cur->info.address, symbolize ? &cur->info : nullptr,
common_flags()->symbolize_vs_style,
common_flags()->strip_path_prefix);
Printf("%s\n", frame_desc.data());
if (dedup_frames-- > 0) {
Expand Down Expand Up @@ -108,7 +114,12 @@ void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf,
uptr out_buf_size) {
if (!out_buf_size) return;
pc = StackTrace::GetPreviousInstructionPc(pc);
SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
SymbolizedStack *frame;
bool symbolize = RenderNeedsSymbolization(fmt);
if (symbolize)
frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
else
frame = SymbolizedStack::New(pc);
if (!frame) {
internal_strncpy(out_buf, "<can't symbolize>", out_buf_size);
out_buf[out_buf_size - 1] = 0;
Expand All @@ -121,7 +132,8 @@ void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf,
for (SymbolizedStack *cur = frame; cur && out_buf < out_end;
cur = cur->next) {
frame_desc.clear();
RenderFrame(&frame_desc, fmt, frame_num++, cur->info,
RenderFrame(&frame_desc, fmt, frame_num++, cur->info.address,
symbolize ? &cur->info : nullptr,
common_flags()->symbolize_vs_style,
common_flags()->strip_path_prefix);
if (!frame_desc.length())
Expand Down
89 changes: 58 additions & 31 deletions compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,14 @@ static const char *DemangleFunctionName(const char *function) {
static const char kDefaultFormat[] = " #%n %p %F %L";

void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
const AddressInfo &info, bool vs_style,
uptr address, const AddressInfo *info, bool vs_style,
const char *strip_path_prefix, const char *strip_func_prefix) {
// info will be null in the case where symbolization is not needed for the
// given format. This ensures that the code below will get a hard failure
// rather than print incorrect information in case RenderNeedsSymbolization
// ever ends up out of sync with this function. If non-null, the addresses
// should match.
CHECK(!info || address == info->address);
if (0 == internal_strcmp(format, "DEFAULT"))
format = kDefaultFormat;
for (const char *p = format; *p != '\0'; p++) {
Expand All @@ -126,71 +132,69 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
buffer->append("%zu", frame_no);
break;
case 'p':
buffer->append("0x%zx", info.address);
buffer->append("0x%zx", address);
break;
case 'm':
buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
buffer->append("%s", StripPathPrefix(info->module, strip_path_prefix));
break;
case 'o':
buffer->append("0x%zx", info.module_offset);
buffer->append("0x%zx", info->module_offset);
break;
case 'f':
buffer->append("%s",
DemangleFunctionName(
StripFunctionName(info.function, strip_func_prefix)));
buffer->append("%s", DemangleFunctionName(StripFunctionName(
info->function, strip_func_prefix)));
break;
case 'q':
buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
? info.function_offset
buffer->append("0x%zx", info->function_offset != AddressInfo::kUnknown
? info->function_offset
: 0x0);
break;
case 's':
buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
buffer->append("%s", StripPathPrefix(info->file, strip_path_prefix));
break;
case 'l':
buffer->append("%d", info.line);
buffer->append("%d", info->line);
break;
case 'c':
buffer->append("%d", info.column);
buffer->append("%d", info->column);
break;
// Smarter special cases.
case 'F':
// Function name and offset, if file is unknown.
if (info.function) {
buffer->append("in %s",
DemangleFunctionName(
StripFunctionName(info.function, strip_func_prefix)));
if (!info.file && info.function_offset != AddressInfo::kUnknown)
buffer->append("+0x%zx", info.function_offset);
if (info->function) {
buffer->append("in %s", DemangleFunctionName(StripFunctionName(
info->function, strip_func_prefix)));
if (!info->file && info->function_offset != AddressInfo::kUnknown)
buffer->append("+0x%zx", info->function_offset);
}
break;
case 'S':
// File/line information.
RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style,
strip_path_prefix);
RenderSourceLocation(buffer, info->file, info->line, info->column,
vs_style, strip_path_prefix);
break;
case 'L':
// Source location, or module location.
if (info.file) {
RenderSourceLocation(buffer, info.file, info.line, info.column,
if (info->file) {
RenderSourceLocation(buffer, info->file, info->line, info->column,
vs_style, strip_path_prefix);
} else if (info.module) {
RenderModuleLocation(buffer, info.module, info.module_offset,
info.module_arch, strip_path_prefix);
} else if (info->module) {
RenderModuleLocation(buffer, info->module, info->module_offset,
info->module_arch, strip_path_prefix);
} else {
buffer->append("(<unknown module>)");
}
break;
case 'M':
// Module basename and offset, or PC.
if (info.address & kExternalPCBit)
{} // There PCs are not meaningful.
else if (info.module)
if (address & kExternalPCBit) {
} // There PCs are not meaningful.
else if (info->module)
// Always strip the module name for %M.
RenderModuleLocation(buffer, StripModuleName(info.module),
info.module_offset, info.module_arch, "");
RenderModuleLocation(buffer, StripModuleName(info->module),
info->module_offset, info->module_arch, "");
else
buffer->append("(%p)", (void *)info.address);
buffer->append("(%p)", (void *)address);
break;
default:
Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
Expand All @@ -200,6 +204,29 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
}
}

bool RenderNeedsSymbolization(const char *format) {
if (0 == internal_strcmp(format, "DEFAULT"))
format = kDefaultFormat;
for (const char *p = format; *p != '\0'; p++) {
if (*p != '%')
continue;
p++;
switch (*p) {
case '%':
break;
case 'n':
// frame_no
break;
case 'p':
// address
break;
default:
return true;
}
}
return false;
}

void RenderData(InternalScopedString *buffer, const char *format,
const DataInfo *DI, const char *strip_path_prefix) {
for (const char *p = format; *p != '\0'; p++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ namespace __sanitizer {
// module+offset if it is known, or (<unknown module>) string.
// %M - prints module basename and offset, if it is known, or PC.
void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
const AddressInfo &info, bool vs_style,
uptr address, const AddressInfo *info, bool vs_style,
const char *strip_path_prefix = "",
const char *strip_func_prefix = "");

bool RenderNeedsSymbolization(const char *format);

void RenderSourceLocation(InternalScopedString *buffer, const char *file,
int line, int column, bool vs_style,
const char *strip_path_prefix);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info,
if (!common_flags()->print_summary) return;
InternalScopedString buff(kMaxSummaryLength);
buff.append("%s ", error_type);
RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style,
RenderFrame(&buff, "%L %F", 0, info.address, &info,
common_flags()->symbolize_vs_style,
common_flags()->strip_path_prefix);
ReportErrorSummary(buff.data(), alt_tool_name);
}
Expand Down
Loading

0 comments on commit 6f010c8

Please sign in to comment.