[llvm] r339864 - [RISCV][MC] Don't fold symbol differences if requiresDiffExpressionRelocations is true

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 16 04:26:38 PDT 2018


Author: asb
Date: Thu Aug 16 04:26:37 2018
New Revision: 339864

URL: http://llvm.org/viewvc/llvm-project?rev=339864&view=rev
Log:
[RISCV][MC] Don't fold symbol differences if requiresDiffExpressionRelocations is true

When emitting the difference between two symbols, the standard behavior is 
that the difference will be resolved to an absolute value if both of the 
symbols are offsets from the same data fragment. This is undesirable on 
architectures such as RISC-V where relaxation in the linker may cause the 
computed difference to become invalid. This caused an issue when compiling to 
object code, where the size of a function in the debug information was already 
calculated even though it could change as a consequence of relaxation in the 
subsequent linking stage.

This patch inhibits the resolution of symbol differences to absolute values 
where the target's AsmBackend has declared that it does not want these to be 
folded.

Differential Revision: https://reviews.llvm.org/D45773
Patch by Edward Jones.


Added:
    llvm/trunk/test/CodeGen/RISCV/fixups-diff.ll
Modified:
    llvm/trunk/include/llvm/MC/MCObjectStreamer.h
    llvm/trunk/lib/MC/MCObjectStreamer.cpp

Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=339864&r1=339863&r2=339864&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Thu Aug 16 04:26:37 2018
@@ -179,7 +179,9 @@ public:
   ///
   /// Emit the absolute difference between \c Hi and \c Lo, as long as we can
   /// compute it.  Currently, that requires that both symbols are in the same
-  /// data fragment.  Otherwise, do nothing and return \c false.
+  /// data fragment and that the target has not specified that diff expressions
+  /// require relocations to be emitted. Otherwise, do nothing and return
+  /// \c false.
   ///
   /// \pre Offset of \c Hi is greater than the offset \c Lo.
   void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,

Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=339864&r1=339863&r2=339864&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Thu Aug 16 04:26:37 2018
@@ -61,9 +61,12 @@ void MCObjectStreamer::flushPendingLabel
 
 // As a compile-time optimization, avoid allocating and evaluating an MCExpr
 // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
-static Optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
-                                             const MCSymbol *Lo) {
+static Optional<uint64_t>
+absoluteSymbolDiff(MCAssembler &Asm, const MCSymbol *Hi, const MCSymbol *Lo) {
   assert(Hi && Lo);
+  if (Asm.getBackendPtr()->requiresDiffExpressionRelocations())
+    return None;
+
   if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
       Hi->isVariable() || Lo->isVariable())
     return None;
@@ -74,7 +77,7 @@ static Optional<uint64_t> absoluteSymbol
 void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
                                               const MCSymbol *Lo,
                                               unsigned Size) {
-  if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
+  if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
     EmitIntValue(*Diff, Size);
     return;
   }
@@ -83,7 +86,7 @@ void MCObjectStreamer::emitAbsoluteSymbo
 
 void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
                                                        const MCSymbol *Lo) {
-  if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
+  if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
     EmitULEB128IntValue(*Diff);
     return;
   }

Added: llvm/trunk/test/CodeGen/RISCV/fixups-diff.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/fixups-diff.ll?rev=339864&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/fixups-diff.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/fixups-diff.ll Thu Aug 16 04:26:37 2018
@@ -0,0 +1,46 @@
+; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=+relax %s -o - \
+; RUN:     | llvm-readobj -r | FileCheck -check-prefix=RELAX %s
+; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=-relax %s -o - \
+; RUN:     | llvm-readobj -r | FileCheck -check-prefix=NORELAX %s
+
+; Check that a difference between two symbols in the same fragment
+; causes relocations to be emitted if and only if relaxation is enabled.
+;
+; This specific test is checking that the size of the function in
+; the debug information is represented by a relocation. This isn't
+; an assembly test as the assembler takes a different path through
+; LLVM, which is already covered by the fixups-expr.s test.
+
+source_filename = "tmp.c"
+target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
+target triple = "riscv32"
+
+define i32 @main() !dbg !7 {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval, align 4
+  ret i32 0
+}
+
+; RELAX: 0x22 R_RISCV_ADD32 - 0x0
+; RELAX: 0x22 R_RISCV_SUB32 - 0x0
+; RELAX: 0x2B R_RISCV_ADD32 - 0x0
+; RELAX: 0x2B R_RISCV_SUB32 - 0x0
+; NORELAX-NOT: R_RISCV_ADD32
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "fixups-diff.ll", directory: "test/MC/RISCV")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang"}
+!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocation(line: 2, column: 3, scope: !7)




More information about the llvm-commits mailing list