new file mode 100644
@@ -0,0 +1,247 @@
+/* Machine description for AArch64 architecture.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_AARCH64_DWARF_METADATA_H
+#define GCC_AARCH64_DWARF_METADATA_H
+
+#include <type_traits>
+#include <cstdint>
+
+#include <vec.h>
+
+namespace aarch64 {
+
+enum attr_val_type: uint8_t
+{
+ uleb128 = 0x0,
+ asciz = 0x1,
+};
+
+enum BA_TagFeature_t: uint8_t
+{
+ Tag_Feature_BTI = 1,
+ Tag_Feature_PAC = 2,
+ Tag_Feature_GCS = 3,
+};
+
+template <typename T_tag, typename T_val>
+struct aeabi_attribute
+{
+ T_tag tag;
+ T_val value;
+};
+
+template <typename T_tag, typename T_val>
+aeabi_attribute<T_tag, T_val>
+make_aeabi_attribute (T_tag tag, T_val val)
+{
+ return aeabi_attribute<T_tag, T_val>{tag, val};
+}
+
+namespace details {
+
+constexpr const char*
+to_c_str (bool b)
+{
+ return b ? "true" : "false";
+}
+
+constexpr const char*
+to_c_str (const char *s)
+{
+ return s;
+}
+
+constexpr const char*
+to_c_str (attr_val_type t)
+{
+ const char *s = nullptr;
+ switch (t) {
+ case uleb128:
+ s = "ULEB128";
+ break;
+ case asciz:
+ s = "asciz";
+ break;
+ }
+ return s;
+}
+
+constexpr const char*
+to_c_str (BA_TagFeature_t feature)
+{
+ const char *s = nullptr;
+ switch (feature) {
+ case Tag_Feature_BTI:
+ s = "Tag_Feature_BTI";
+ break;
+ case Tag_Feature_PAC:
+ s = "Tag_Feature_PAC";
+ break;
+ case Tag_Feature_GCS:
+ s = "Tag_Feature_GCS";
+ break;
+ }
+ return s;
+}
+
+template <
+ typename T,
+ typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
+>
+constexpr const char*
+aeabi_attr_str_fmt (T phantom __attribute__((unused)))
+{
+ return "\t.aeabi_attribute %u, %u";
+}
+
+constexpr const char*
+aeabi_attr_str_fmt (const char *phantom __attribute__((unused)))
+{
+ return "\t.aeabi_attribute %u, \"%s\"";
+}
+
+template <
+ typename T,
+ typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
+>
+constexpr uint8_t
+aeabi_attr_val_for_fmt (T value)
+{
+ return static_cast<uint8_t>(value);
+}
+
+constexpr const char*
+aeabi_attr_val_for_fmt (const char *s)
+{
+ return s;
+}
+
+template <typename T_tag, typename T_val>
+void write (FILE *out_file, aeabi_attribute<T_tag, T_val> const &attr)
+{
+ asm_fprintf (out_file, aeabi_attr_str_fmt(T_val{}),
+ attr.tag, aeabi_attr_val_for_fmt(attr.value));
+ if (flag_debug_asm)
+ asm_fprintf (out_file, "\t%s %s: %s", ASM_COMMENT_START,
+ to_c_str(attr.tag), to_c_str(attr.value));
+ asm_fprintf (out_file, "\n");
+}
+
+template <
+ typename T,
+ typename = typename std::enable_if<std::is_unsigned<T>::value, T>::type
+>
+constexpr attr_val_type
+deduce_attr_av_type (T value __attribute__((unused)))
+{
+ return attr_val_type::uleb128;
+}
+
+constexpr attr_val_type
+deduce_attr_av_type (const char* value __attribute__((unused)))
+{
+ return attr_val_type::asciz;
+}
+
+} // namespace details
+
+/* AEABI subsections can be public or private. A subsection is public if it is
+ prefixed with "aeabi", private otherwise. The header of an AEABI subsection
+ is composed of a name (usually a vendor name), a status whether it is
+ optional or not, and the expected type of its associated attributes (ULEB128
+ or asciz). Note: The attributes in the same subsection have all the same
+ type. An attribute is composed of a tag identifier (ULEB128), and its value
+ (ULEB128 or asciz).
+
+ Syntax:
+ .aeabi_subsection NameOfTheSubsection: string (=asciz),
+ Optional: boolean (=ULEB128),
+ AttributeValueType: enum{ULEB128, asciz} (=ULEB128)
+ [
+ .aeabi_attribute TagIdentifier: ULEB128,
+ TagValue: Variant[ULEB128|asciz]
+ ]*
+
+ Example:
+ .aeabi_subsection .aeabi-feature-and-bits, 1, 0
+ // Optional: true, AttrValType: ULEB128
+ .aeabi_attribute 3, 1 // Tag_Feature_GCS: true
+
+ Note: The textual representations of the tag and its value are emitted as a
+ comment along their numerical representations to annotate the assembler
+ output when the developer flag '-dA' is provided. */
+template <
+ typename T_tag, /* The type of a tag. */
+ typename T_val, /* The type of a value. */
+ size_t N = 0 /* The number of expected attributes if we know it. */
+>
+class aeabi_subsection
+{
+ public:
+ aeabi_subsection (const char *name, bool optional):
+ name_(name),
+ optional_(optional),
+ avtype_(details::deduce_attr_av_type (T_val{}))
+ {}
+
+ /* Append an attribute to the subsection. */
+ void
+ append (aeabi_attribute<T_tag, T_val> &&attr)
+ {
+ attributes_.quick_push (std::move(attr));
+ }
+
+ /* Write the data to the assembly file. */
+ void
+ write (FILE *out_file) const
+ {
+ asm_fprintf (out_file, "\t.aeabi_subsection %s, %u, %u",
+ name_, static_cast<uint8_t>(optional_),
+ static_cast<uint8_t>(avtype_));
+ if (flag_debug_asm)
+ asm_fprintf (out_file, "\t%s Optional: %s, AttrValType: %s",
+ ASM_COMMENT_START,
+ details::to_c_str(optional_),
+ details::to_c_str(avtype_));
+ asm_fprintf (out_file, "\n");
+
+ for (auto const& attr: attributes_)
+ {
+ details::write (out_file, attr);
+ }
+ }
+
+ /* Indicate if the subsection is empty. */
+ bool empty() const
+ {
+ return attributes_.is_empty ();
+ }
+
+ private:
+ const char *name_;
+ bool optional_;
+ attr_val_type avtype_;
+ auto_vec<aeabi_attribute<T_tag, T_val>, N> attributes_;
+};
+
+} // namespace aarch64
+
+#endif /* GCC_AARCH64_DWARF_METADATA_H */
\ No newline at end of file
@@ -83,6 +83,7 @@
#include "rtlanal.h"
#include "tree-dfa.h"
#include "asan.h"
+#include "aarch64-dwarf-metadata.h"
#include "aarch64-feature-deps.h"
#include "config/arm/aarch-common.h"
#include "config/arm/aarch-common-protos.h"
@@ -24677,33 +24678,6 @@ aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED)
asm_fprintf (f, "\t.cfi_b_key_frame\n");
}
-/* This function is used to emit an AEABI attribute with tag and its associated
- value. We emit the numerical value of the tag and the textual tags as
- comment so that anyone reading the assembler output will know which tag is
- being set.
- example: .aeabi_attribute 3, 1 // Tag_Feature_GCS */
-
-void
-aarch64_emit_aeabi_attribute (const char *name, uint8_t num, uint8_t val)
-{
- asm_fprintf (asm_out_file, "\t.aeabi_attribute %u, %u", num, val);
- if (flag_debug_asm)
- asm_fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, name);
- asm_fprintf (asm_out_file, "\n");
-}
-
-/* This function is used to emit an AEABI subsection with vendor name,
- optional status and value type.
- example: .aeabi_subsection .aeabi-feature-and-bits, 1, 0 */
-
-void
-aarch64_emit_aeabi_subsection (const char *name, uint8_t num, uint8_t val)
-{
- asm_fprintf (asm_out_file, "\t.aeabi_subsection %s, %u, %u\n",
- name, num, val);
-}
-
-
/* Implements TARGET_ASM_FILE_START. Output the assembly header. */
static void
@@ -24727,18 +24701,21 @@ aarch64_start_file (void)
/* Emit gcs build attributes only when building a native AArch64-hosted
compiler. */
#if defined(__aarch64__)
+ using namespace aarch64;
+ aeabi_subsection<BA_TagFeature_t, bool, 3>
+ aeabi_subsec (".aeabi-feature-and-bits", true);
+
/* Check the current assembly supports gcs build attributes, if not
fallback to .note.gnu.property section. */
#ifdef HAVE_AS_BUILD_ATTRIBUTES_GCS
- if (aarch64_gcs_enabled ())
- {
- aarch64_emit_aeabi_subsection (".aeabi-feature-and-bits", 1, 0);
- aarch64_emit_aeabi_attribute ("Tag_Feature_GCS", 3, 1);
- }
+ aeabi_subsec.append (
+ make_aeabi_attribute (Tag_Feature_GCS, aarch64_gcs_enabled ()));
#endif
+ if (!aeabi_subsec.empty ())
+ aeabi_subsec.write(asm_out_file);
#endif
- default_file_start ();
+ default_file_start ();
}
/* Emit load exclusive. */
@@ -6,7 +6,7 @@ int main()
return 0;
}
-/* { dg-final { scan-assembler "\.aeabi_subsection \.aeabi-feature-and-bits, 1, 0" } } */
-/* { dg-final { scan-assembler "\.aeabi_attribute 3, 1\t\/\/ Tag_Feature_GCS" } } */
+/* { dg-final { scan-assembler "\.aeabi_subsection \.aeabi-feature-and-bits, 1, 0\t\/\/ Optional: true, AttrValType: ULEB128" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute 3, 1\t\/\/ Tag_Feature_GCS: true" } } */
/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */
/* { dg-final { scan-assembler "\.word\t4\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(GCS\\)" } } */
\ No newline at end of file
@@ -6,7 +6,7 @@ int main()
return 0;
}
-/* { dg-final { scan-assembler "\.aeabi_subsection \.aeabi-feature-and-bits, 1, 0" } } */
-/* { dg-final { scan-assembler "\.aeabi_attribute 3, 1\t\/\/ Tag_Feature_GCS" } } */
+/* { dg-final { scan-assembler "\.aeabi_subsection \.aeabi-feature-and-bits, 1, 0\t\/\/ Optional: true, AttrValType: ULEB128" } } */
+/* { dg-final { scan-assembler "\.aeabi_attribute 3, 1\t\/\/ Tag_Feature_GCS: true" } } */
/* { dg-final { scan-assembler "\.section\t\.note\.gnu\.property" } } */
/* { dg-final { scan-assembler "\.word\t7\t\/\/ GNU_PROPERTY_AARCH64_FEATURE_1_AND \\(BTI, PAC, GCS\\)" } } */
\ No newline at end of file