Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -7092,6 +7092,15 @@ %a.addr = alloca float*, align 8, !annotation !0 !0 = !{!"auto-init"} +'``explicit_size``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``explicit_size`` metadata is used to emit a size directive with a different +size than the objects total size. This can be useful when an object contains +more bytes than are actually accessible or meaninfully part of the object. It +will emit any size given without any error checking, even if that size isn't +meaningful. + Module Flags Metadata ===================== Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -690,10 +690,21 @@ emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); - if (MAI->hasDotTypeDotSizeDirective()) + if (MAI->hasDotTypeDotSizeDirective()) { + [&Size, GV] { + const MDNode *ExplicitValue = GV->getMetadata("explicit_size"); + if (!ExplicitValue || !ExplicitValue->getNumOperands()) + return; + const auto *MetadataValue = dyn_cast(ExplicitValue->getOperand(0)); + if (!MetadataValue) + return; + if (const auto *CI = dyn_cast(MetadataValue->getValue())) + Size = CI->getZExtValue(); + }(); // .size foo, 42 OutStreamer->emitELFSize(EmittedInitSym, MCConstantExpr::create(Size, OutContext)); + } OutStreamer->AddBlankLine(); } Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2510,6 +2510,11 @@ // zero so we can copy the metadata over as is. NewGlobal->copyMetadata(G, 0); + LLVMContext &C = NewGlobal->getContext(); + ConstantInt *Int = ConstantInt::get(C, APInt{64, SizeInBytes}); + MDNode *N = MDNode::get(C, ConstantAsMetadata::get(Int)); + NewGlobal->setMetadata("explicit_size", N); + Value *Indices2[2]; Indices2[0] = IRB.getInt32(0); Indices2[1] = IRB.getInt32(0); Index: llvm/test/CodeGen/X86/explicit-size-metadata.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/explicit-size-metadata.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s + +@a = dso_local global i64 0, align 8, !explicit_size !0 +; CHECK: .size a, 4 + +@b = dso_local global i64 0, align 8 +; CHECK: .size b, 8 + +@larger = dso_local global i16 0, align 4, !explicit_size !0 +; CHECK: .size larger, 4 + +!0 = !{i64 4} Index: llvm/test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll +++ llvm/test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll @@ -6,14 +6,14 @@ ; Here we check that the global redzone sizes grow with the object size. @G10 = global [10 x i8] zeroinitializer, align 1 -; CHECK: @G10 = global { [10 x i8], [22 x i8] } +; CHECK: @G10 = global { [10 x i8], [22 x i8] } zeroinitializer, align 32, !explicit_size ![[TAG10:.*]] @G31 = global [31 x i8] zeroinitializer, align 1 @G32 = global [32 x i8] zeroinitializer, align 1 @G33 = global [33 x i8] zeroinitializer, align 1 -; CHECK: @G31 = global { [31 x i8], [33 x i8] } -; CHECK: @G32 = global { [32 x i8], [32 x i8] } -; CHECK: @G33 = global { [33 x i8], [63 x i8] } +; CHECK: @G31 = global { [31 x i8], [33 x i8] } zeroinitializer, align 32, !explicit_size ![[TAG31:.*]] +; CHECK: @G32 = global { [32 x i8], [32 x i8] } zeroinitializer, align 32, !explicit_size ![[TAG32:.*]] +; CHECK: @G33 = global { [33 x i8], [63 x i8] } zeroinitializer, align 32, !explicit_size ![[TAG33:.*]] @G63 = global [63 x i8] zeroinitializer, align 1 @G64 = global [64 x i8] zeroinitializer, align 1 @@ -55,4 +55,10 @@ @G100000000 = global [100000000 x i8] zeroinitializer, align 1 ; CHECK: @G1000000 = global { [1000000 x i8], [249984 x i8] } ; CHECK: @G10000000 = global { [10000000 x i8], [262144 x i8] } -; CHECK: @G100000000 = global { [100000000 x i8], [262144 x i8] } +; CHECK: @G100000000 = global { [100000000 x i8], [262144 x i8] } zeroinitializer, align 32, !explicit_size ![[TAGBIG:.*]] + +; CHECK: ![[TAG10]] = !{i64 10} +; CHECK: ![[TAG31]] = !{i64 31} +; CHECK: ![[TAG32]] = !{i64 32} +; CHECK: ![[TAG33]] = !{i64 33} +; CHECK: ![[TAGBIG]] = !{i64 100000000} Index: llvm/test/Instrumentation/AddressSanitizer/debug-info-global-var.ll =================================================================== --- llvm/test/Instrumentation/AddressSanitizer/debug-info-global-var.ll +++ llvm/test/Instrumentation/AddressSanitizer/debug-info-global-var.ll @@ -2,7 +2,7 @@ source_filename = "version.c" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.12.0" -; CHECK: @version = constant { [5 x i8], [27 x i8] } {{.*}}, !dbg ![[GV:.*]] +; CHECK: @version = constant { [5 x i8], [27 x i8] } {{.*}}, !dbg ![[GV:.*]], @version = constant [5 x i8] c"4.00\00", align 1, !dbg !0