/* { dg-options "-Wno-discarded-array-qualifiers" } */
/* The MMIX port always switches to the .data section at the end of a file. */
/* { dg-final { scan-assembler-not "\\.data(?!\\.rel\\.ro)" { xfail powerpc*-*-aix* mmix-*-* x86_64-*-mingw* } } } */
+/* { dg-final { scan-assembler-symbol-section {^_?a$} {^\.(const|rodata)} } } */
static const int a[2] = { 1, 2 };
+/* { dg-final { scan-assembler-symbol-section {^_?a1$} {^\.(const|rodata)} } } */
const int a1[2] = { 1, 2 };
typedef const int ci;
+/* { dg-final { scan-assembler-symbol-section {^_?b$} {^\.(const|rodata)} } } */
static ci b[2] = { 3, 4 };
+/* { dg-final { scan-assembler-symbol-section {^_?b1$} {^\.(const|rodata)} } } */
ci b1[2] = { 3, 4 };
typedef int ia[2];
+/* { dg-final { scan-assembler-symbol-section {^_?c$} {^\.(const|rodata)} } } */
static const ia c = { 5, 6 };
+/* { dg-final { scan-assembler-symbol-section {^_?c1$} {^\.(const|rodata)} } } */
const ia c1 = { 5, 6 };
typedef const int cia[2];
+/* { dg-final { scan-assembler-symbol-section {^_?d$} {^\.(const|rodata)} } } */
static cia d = { 7, 8 };
+/* { dg-final { scan-assembler-symbol-section {^_?d1$} {^\.(const|rodata)} } } */
cia d1 = { 7, 8 };
+/* { dg-final { scan-assembler-symbol-section {^_?e$} {^\.(const|rodata)} } } */
static cia e[2] = { { 1, 2 }, { 3, 4 } };
+/* { dg-final { scan-assembler-symbol-section {^_?e1$} {^\.(const|rodata)} } } */
cia e1[2] = { { 1, 2 }, { 3, 4 } };
+/* { dg-final { scan-assembler-symbol-section {^_?p$} {^\.(const|rodata)} } } */
void *const p = &a;
+/* { dg-final { scan-assembler-symbol-section {^_?q$} {^\.(const|rodata)} } } */
void *const q = &b;
+/* { dg-final { scan-assembler-symbol-section {^_?r$} {^\.(const|rodata)} } } */
void *const r = &c;
+/* { dg-final { scan-assembler-symbol-section {^_?s$} {^\.(const|rodata)} } } */
void *const s = &d;
+/* { dg-final { scan-assembler-symbol-section {^_?t$} {^\.(const|rodata)} } } */
void *const t = &e;
+/* { dg-final { scan-assembler-symbol-section {^_?p1$} {^\.(const|rodata)} } } */
void *const p1 = &a1;
+/* { dg-final { scan-assembler-symbol-section {^_?q1$} {^\.(const|rodata)} } } */
void *const q1 = &b1;
+/* { dg-final { scan-assembler-symbol-section {^_?r1$} {^\.(const|rodata)} } } */
void *const r1 = &c1;
+/* { dg-final { scan-assembler-symbol-section {^_?s1$} {^\.(const|rodata)} } } */
void *const s1 = &d1;
+/* { dg-final { scan-assembler-symbol-section {^_?t1$} {^\.(const|rodata)} } } */
void *const t1 = &e1;
--- /dev/null
+// Test the scan-symbol-section directive.
+
+// { dg-do preprocess }
+
+// The .section directive changes the section for all following symbols.
+ .section .text
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_1$} {^\.text$} } }
+_test_function_1:
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_2$} {^\.text$} } }
+_test_function_2:
+
+// For ELF targets, the .section directive can take multiple arguments.
+ .section .other_text_section,"ax",progbits
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_elf_function$} {^\.other_text_section$} } }
+_test_elf_function:
+
+// For Mach-O targets, the .section directive takes a segment name and a section name.
+ .section __TEXT,__my_text_section
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_macho_function$} {^__TEXT,__my_text_section$} } }
+_test_macho_function:
+// Extra whitespace between .section arguments should be ignored.
+ .section __DATA , __testsection
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_macho_var$} {^__DATA,__testsection$} } }
+_test_macho_var:
+
+// The .data directive sets the section for all following symbols to '.data'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_var_1$} {^\.data$} } }
+ .data
+_test_var_1:
+
+// The .text directive sets the section for all following symbols to '.text'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_3$} {^\.text$} } }
+ .text
+_test_function_3:
+
+// The .const directive sets the section for all following symbols to '.const'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_data_1$} {^\.const$} } }
+ .const
+_test_data_1:
+
+// Other directives do not affect the section of following symbols.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_var_2$} {^\.data$} } }
+ .data
+ .p2align 2
+ .size _test_var_2, 4
+_test_var_2:
+
+// Symbol name patterns can match multiple symbols, and section name patterns
+// can match multiple sections.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i" {^_test_function_} {^(\.|__TEXT,).*text} } }
set pattern [lindex $orig_args 0]
set printable_pattern [make_pattern_printable $pattern]
- if { [is_remote host] } {
- remote_upload host "$output_file"
- }
- set files [glob -nocomplain $output_file]
+ set files [dg_glob_remote $output_file]
if { $files == "" } {
verbose -log "$testcase: output file does not exist"
unresolved "$testcase $name $printable_pattern"
}
}
+proc dg_glob_remote { file_pattern } {
+ if { [is_remote host] } {
+ remote_upload host $file_pattern
+ }
+ return [glob -nocomplain $file_pattern]
+}
+
# Look for a pattern in the .s file produced by the compiler. See
# dg-scan for details.
dg-scan "scan-not-hidden" 0 $testcase $output_file $args
}
+# Check that symbols are emitted in the desired section.
+# Like scan-symbol-section, but using the assembly output generated by
+# the compiler.
+#
+# Example:
+#
+# // All numbered functions (func1, func2, etc.) must be in the .text section or
+# // in a .text sub-section (like .text._func1).
+# { dg-final { scan-assembler-symbol-section {^_func[1-5]$} {^\.text($|\.)} } }
+
+proc scan-assembler-symbol-section { args } {
+ set testcase [testname-for-summary]
+ set filename [lindex $testcase 0]
+ set output_file "[file rootname [file tail $filename]].s"
+ set symbol_pattern [lindex $args 0]
+ set expected_section_pattern [lindex $args 1]
+ dg-scan-symbol-section \
+ "scan-assembler-symbol-section" \
+ $testcase \
+ $output_file \
+ $symbol_pattern \
+ $expected_section_pattern
+}
+
+# Check that symbols are emitted in the desired section.
+#
+# Symbols and sections are interpreted as regexp patterns.
+#
+# If no matching symbol is found, scan-symbol-section reports a FAILure.
+#
+# Usage:
+#
+# { dg-final { scan-symbol-section FILENAME SYMBOL SECTION } }
+#
+# Examples:
+#
+# // The my_var C symbol must be in the .data section (or in a .data._my_var section
+# // if -ffunction-sections is in use).
+# { dg-final { scan-symbol-section "my-test.s" {^_my_var$} {^\.data(\._my_var)?$} } }
+#
+# // All numbered functions (func1, func2, etc.) must be in the .text section
+# // (and not in any other section like .text._func1).
+# { dg-final { scan-symbol-section "my-test.s" {^_func[1-5]$} {^\.text$} } }
+#
+# Caveats:
+#
+# * Only ELF and Mach-O targets are supported. Other
+# targets, like PE/COFF, might appear to work.
+# * For Mach-O targets, the section name matched by scan-symbol-section has one
+# of two forms:
+# * The Mach-O segment name followed by a comma (',') followed by the Mach-O
+# section name. For example, "__TEXT,__text". (There is no whitespace
+# between the Mach-O segment name and the Mach-O section name.)
+# * ".const", ".data", or ".text". For example, the .text assembler directive
+# causes the section name to be ".text" (not "__TEXT,__text"). (However, a
+# directive such as .section __TEXT,__text will cause the section name to be
+# "__TEXT,__text".)
+# * Because scan-symbol-section parses assembly code, scan-symbol-section is
+# unaware of section rewriting performed by the linker. For example, the
+# sections .text._f1 and .text._f2 would normally be merged by binutils'
+# linker into one section called .text, but scan-symbol-section reports the
+# sections as .text._f1 and .text._f2 (and not .text).
+# * The symbol pattern matches any assembly label, including local labels which
+# begin with `.L`.
+
+proc scan-symbol-section { args } {
+ set testcase [testname-for-summary]
+ set output_file [lindex $args 0]
+ set symbol_pattern [lindex $args 1]
+ set expected_section_pattern [lindex $args 2]
+ dg-scan-symbol-section \
+ "scan-symbol-section" \
+ $testcase \
+ $output_file \
+ $symbol_pattern \
+ $expected_section_pattern
+}
+
+# Check that symbols are emitted in the desired section.
+#
+# Avoid calling this function directly. In tests, use scan-symbol-section,
+# scan-assembler-symbol-section, or scan-lto-assembler-symbol-section instead.
+
+proc dg-scan-symbol-section { name testcase output_file symbol_pattern expected_section_pattern } {
+ set printable_symbol_pattern [make_pattern_printable $symbol_pattern]
+ set printable_expected_section_pattern [make_pattern_printable $expected_section_pattern]
+
+ set files [dg_glob_remote $output_file]
+ if { $files == "" } {
+ verbose -log "$testcase: output file does not exist"
+ unresolved "$testcase $name symbol $printable_symbol_pattern has section $printable_expected_section_pattern"
+ return
+ }
+
+ parse_section_of_symbols $output_file section_by_symbol
+
+ set found_symbol 0
+ foreach symbol_name [lsort [array names section_by_symbol]] {
+ if { [regexp -- $symbol_pattern $symbol_name] } {
+ set section $section_by_symbol($symbol_name)
+ set description "$testcase $name symbol $printable_symbol_pattern (found $symbol_name) has section $printable_expected_section_pattern"
+ if { $section == "" } {
+ fail "$description (no section detected)"
+ } else {
+ set description "$description (found $section)"
+ if { [regexp -- $expected_section_pattern $section] } {
+ pass $description
+ } else {
+ fail $description
+ }
+ }
+ set found_symbol 1
+ }
+ }
+ if { ! $found_symbol } {
+ fail "$testcase $name symbol $printable_symbol_pattern (symbol not found) has section $printable_expected_section_pattern"
+ }
+}
+
+# Extract a symbol and section names from pre-processed assembly source code.
+#
+# This function adds entries in the RESULT array where the key is the symbol's
+# name (including any leading underscores) and the value is the section's name
+# (including any leading periods).
+#
+# For example, given the following assembly source code in file.s:
+#
+# .text
+# .function _my_function
+# _my_function:
+# nop
+# .data
+# _my_data:
+# .long 42
+#
+# Executing 'parse_section_of_symbols "file.s" symbols' would have the same
+# effect as the following code:
+#
+# set $result(_my_function) .text
+# set $result(_my_data) .data
+
+proc parse_section_of_symbols { filename result } {
+ upvar $result up_result
+
+ set section_pattern {^\s*(?:\.section\s+(.*)|(\.const|\.data|\.text)\s*)$}
+ set label_pattern {^(\S+):$}
+
+ set fd [open $filename r]
+ set current_section ""
+ while { [gets $fd line] >= 0 } {
+ if { [regexp -- $label_pattern $line dummy symbol_name] } {
+ set up_result($symbol_name) $current_section
+ } elseif { [regexp -- $section_pattern $line dummy section_directive_arguments full_section_directive] } {
+ if { $full_section_directive eq "" } {
+ # Example: .section .text,"ax",progbits
+ # Example: .section __TEXT,__text
+ set arguments [split $section_directive_arguments ","]
+ set current_section [string trim [lindex $arguments 0]]
+ set arg_1 [string trim [lindex $arguments 1]]
+ if { [regexp {^_} $arg_1] } {
+ # The second argument looks like a Mach-O section name.
+ set current_section "$current_section,$arg_1"
+ }
+ } else {
+ # Example: .text
+ set current_section "$full_section_directive"
+ }
+ }
+ }
+ close $fd
+}
+
# Look for a pattern in OUTPUT_FILE. See dg-scan for details.
proc scan-file { output_file args } {