[llvm] a5bd75a - [MSP430] Enable some basic support for debug information

Anton Korobeynikov via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 22 03:16:53 PDT 2020


Author: Anatoly Trosinenko
Date: 2020-06-22T13:14:07+03:00
New Revision: a5bd75aab861df8cea8d1c6b88e764ad4a2c09ea

URL: https://github.com/llvm/llvm-project/commit/a5bd75aab861df8cea8d1c6b88e764ad4a2c09ea
DIFF: https://github.com/llvm/llvm-project/commit/a5bd75aab861df8cea8d1c6b88e764ad4a2c09ea.diff

LOG: [MSP430] Enable some basic support for debug information

This commit technically permits LLVM to emit the debug information for ELF files for MSP430 architecture. Aside from this, it only defines the register numbers as defined by part 10.1 of MSP430 EABI specification (assuming the 1-byte subregisters share the register numbers with corresponding full-size registers).

This commit was basically tested by me with TI-provided GCC 8.3.1 toolchain by compiling an example program with `clang` (please note manual linking may be required due to upstream `clang` not yet handling the `-msim` option necessary to run binaries on the GDB-provided simulator) and then running it and single-stepping with `msp430-elf-gdb` like this:

```
$sysroot/bin/msp430-elf-gdb ./test -ex "target sim" -ex "load ./test"
(gdb) ... traditional GDB commands follow ...
```

While this implementation is most probably far from completeness and is considered experimental, it can already help with debugging MSP430 programs as well as finding issues in LLVM debug info support for MSP430 itself.

One of the use cases includes trying to find a point where UBSan check in a trap-on-error mode was triggered.

The expected debug information format is described in the [MSP430 Embedded Application Binary Interface](http://www.ti.com/lit/an/slaa534/slaa534.pdf) specification, part 10.

Differential Revision: https://reviews.llvm.org/D81488

Added: 
    llvm/test/DebugInfo/MSP430/dwarf-basics.ll

Modified: 
    llvm/lib/Object/RelocationResolver.cpp
    llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
    llvm/lib/Target/MSP430/MSP430RegisterInfo.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp
index d45da76280dd..3f3f79b0f4ff 100644
--- a/llvm/lib/Object/RelocationResolver.cpp
+++ b/llvm/lib/Object/RelocationResolver.cpp
@@ -127,6 +127,27 @@ static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
   }
 }
 
+static bool supportsMSP430(uint64_t Type) {
+  switch (Type) {
+  case ELF::R_MSP430_32:
+  case ELF::R_MSP430_16_BYTE:
+    return true;
+  default:
+    return false;
+  }
+}
+
+static uint64_t resolveMSP430(RelocationRef R, uint64_t S, uint64_t A) {
+  switch (R.getType()) {
+  case ELF::R_MSP430_32:
+    return (S + getELFAddend(R)) & 0xFFFFFFFF;
+  case ELF::R_MSP430_16_BYTE:
+    return (S + getELFAddend(R)) & 0xFFFF;
+  default:
+    llvm_unreachable("Invalid relocation type");
+  }
+}
+
 static bool supportsPPC64(uint64_t Type) {
   switch (Type) {
   case ELF::R_PPC64_ADDR32:
@@ -614,6 +635,8 @@ getRelocationResolver(const ObjectFile &Obj) {
     case Triple::mipsel:
     case Triple::mips:
       return {supportsMips32, resolveMips32};
+    case Triple::msp430:
+      return {supportsMSP430, resolveMSP430};
     case Triple::sparc:
       return {supportsSparc32, resolveSparc32};
     case Triple::hexagon:

diff  --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
index 6117567dcaea..de07b47096d3 100644
--- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
+++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
@@ -24,4 +24,6 @@ MSP430MCAsmInfo::MSP430MCAsmInfo(const Triple &TT,
 
   AlignmentIsInBytes = false;
   UsesELFSectionDirectiveForBSS = true;
+
+  SupportsDebugInformation = true;
 }

diff  --git a/llvm/lib/Target/MSP430/MSP430RegisterInfo.td b/llvm/lib/Target/MSP430/MSP430RegisterInfo.td
index 11003dba383f..0ba8e1c7ebb6 100644
--- a/llvm/lib/Target/MSP430/MSP430RegisterInfo.td
+++ b/llvm/lib/Target/MSP430/MSP430RegisterInfo.td
@@ -15,6 +15,7 @@ class MSP430Reg<bits<4> num, string n, list<string> alt = []> : Register<n> {
   let Namespace = "MSP430";
   let HWEncoding{3-0} = num;
   let AltNames = alt;
+  let DwarfNumbers = [num];
 }
 
 class MSP430RegWithSubregs<bits<4> num, string n, list<Register> subregs,
@@ -24,6 +25,7 @@ class MSP430RegWithSubregs<bits<4> num, string n, list<Register> subregs,
   let Namespace = "MSP430";
   let HWEncoding{3-0} = num;
   let AltNames = alt;
+  let DwarfNumbers = [num];
 }
 
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/test/DebugInfo/MSP430/dwarf-basics.ll b/llvm/test/DebugInfo/MSP430/dwarf-basics.ll
new file mode 100644
index 000000000000..be875a672c05
--- /dev/null
+++ b/llvm/test/DebugInfo/MSP430/dwarf-basics.ll
@@ -0,0 +1,136 @@
+; RUN: llc --filetype=obj -o %t < %s
+; RUN: llvm-dwarfdump --debug-info %t | FileCheck %s
+; RUN: llvm-dwarfdump --verify %t
+
+; This file was based on output of
+;
+;   clang -target msp430 -S -emit-llvm -gdwarf-3 -Os dwarf-basics.c
+;
+; for the following dwarf-basics.c
+;
+;   struct X {
+;     void *a;
+;   };
+;
+;   int f(long y, struct X *p)
+;   {
+;     return 42;
+;   }
+;
+
+; CHECK: file format elf32-msp430
+
+; CHECK: .debug_info contents:
+; CHECK: Compile Unit: length = 0x{{.*}}, format = DWARF32, version = 0x0003, abbr_offset = 0x0000, addr_size = 0x02 (next unit at 0x{{.*}})
+
+; CHECK: DW_TAG_compile_unit
+; CHECK:   DW_AT_producer    ("clang version 11.0.0 (git at ...)")
+; CHECK:   DW_AT_language    (DW_LANG_C99)
+; CHECK:   DW_AT_name        ("dwarf-basics.c")
+; CHECK:   DW_AT_stmt_list   (0x{{.*}})
+; CHECK:   DW_AT_comp_dir    ("/tmp")
+; CHECK:   DW_AT_low_pc      (0x{{.*}})
+; CHECK:   DW_AT_high_pc     (0x{{.*}})
+
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_low_pc    (0x{{.*}})
+; CHECK:     DW_AT_high_pc   (0x{{.*}})
+; CHECK:     DW_AT_frame_base        (DW_OP_reg1 SPB)
+; CHECK:     DW_AT_name      ("f")
+; CHECK:     DW_AT_decl_file ("/tmp/dwarf-basics.c")
+; CHECK:     DW_AT_decl_line (5)
+; CHECK:     DW_AT_prototyped        (0x01)
+; CHECK:     DW_AT_type      (0x{{.*}} "int")
+; CHECK:     DW_AT_external  (0x01)
+
+; CHECK:       DW_TAG_formal_parameter
+; CHECK:         DW_AT_location        (0x{{.*}}:
+; CHECK:            [0x0000, 0x0004): DW_OP_reg12 R12B)
+; CHECK:         DW_AT_name    ("y")
+; CHECK:         DW_AT_decl_file       ("/tmp/dwarf-basics.c")
+; CHECK:         DW_AT_decl_line       (5)
+; CHECK:         DW_AT_type    (0x{{.*}} "long int")
+
+; CHECK:       DW_TAG_formal_parameter
+; CHECK:         DW_AT_location        (DW_OP_reg14 R14B)
+; CHECK:         DW_AT_name    ("p")
+; CHECK:         DW_AT_decl_file       ("/tmp/dwarf-basics.c")
+; CHECK:         DW_AT_decl_line       (5)
+; CHECK:         DW_AT_type    (0x{{.*}} "X*")
+
+; CHECK:       NULL
+
+; CHECK:     DW_TAG_base_type
+; CHECK:       DW_AT_name      ("int")
+; CHECK:       DW_AT_encoding  (DW_ATE_signed)
+; CHECK:       DW_AT_byte_size (0x02)
+
+; CHECK:     DW_TAG_base_type
+; CHECK:       DW_AT_name      ("long int")
+; CHECK:       DW_AT_encoding  (DW_ATE_signed)
+; CHECK:       DW_AT_byte_size (0x04)
+
+; CHECK:     DW_TAG_pointer_type
+; CHECK:       DW_AT_type      (0x{{.*}} "X")
+
+; CHECK:     DW_TAG_structure_type
+; CHECK:       DW_AT_name      ("X")
+; CHECK:       DW_AT_byte_size (0x02)
+; CHECK:       DW_AT_decl_file ("/tmp/dwarf-basics.c")
+; CHECK:       DW_AT_decl_line (1)
+
+; CHECK:       DW_TAG_member
+; CHECK:         DW_AT_name    ("a")
+; CHECK:         DW_AT_type    (0x{{.*}} "*")
+; CHECK:         DW_AT_decl_file       ("/tmp/dwarf-basics.c")
+; CHECK:         DW_AT_decl_line       (2)
+; CHECK:         DW_AT_data_member_location    (0x00)
+
+; CHECK:       NULL
+
+; CHECK:     DW_TAG_pointer_type
+
+; CHECK:     NULL
+
+
+source_filename = "dwarf-basics.c"
+target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16"
+target triple = "msp430"
+
+%struct.X = type { i8* }
+
+define i16 @f(i32 %y, %struct.X* %p) !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %y, metadata !18, metadata !DIExpression()), !dbg !20
+  call void @llvm.dbg.value(metadata %struct.X* %p, metadata !19, metadata !DIExpression()), !dbg !20
+  ret i16 42, !dbg !21
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0 (git at ...)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "dwarf-basics.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 3}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 2}
+!6 = !{!"clang version 11.0.0 (git at ...)"}
+!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 5, type: !8, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !17)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !11, !12}
+!10 = !DIBasicType(name: "int", size: 16, encoding: DW_ATE_signed)
+!11 = !DIBasicType(name: "long int", size: 32, encoding: DW_ATE_signed)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 16)
+!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", file: !1, line: 1, size: 16, elements: !14)
+!14 = !{!15}
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !13, file: !1, line: 2, baseType: !16, size: 16)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 16)
+!17 = !{!18, !19}
+!18 = !DILocalVariable(name: "y", arg: 1, scope: !7, file: !1, line: 5, type: !11)
+!19 = !DILocalVariable(name: "p", arg: 2, scope: !7, file: !1, line: 5, type: !12)
+!20 = !DILocation(line: 0, scope: !7)
+!21 = !DILocation(line: 7, column: 3, scope: !7)


        


More information about the llvm-commits mailing list