[PATCH] D36823: [LLD][ELF] Read ARM BuildAttributes section to determine supported features.

Peter Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 27 07:22:19 PST 2017


peter.smith added a comment.

Putting comment in Phabricator from llvm-commits

> Index: test/ELF/arm-bl-v6.s
>  ===================================================================
> 
> - /dev/null +++ test/ELF/arm-bl-v6.s @@ -0,0 +1,50 @@ +// RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t +// RUN: ld.lld %t -o %t2 2>&1 | FileCheck %s +// Requires: arm + +// On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the +// extended range encoding is not supported. The following example has a Thumb +// BL that is out of range on ARM v6 and requires a range extension thunk. +// As v6 does not support MOVT or MOVW instructions the Thunk must not +// use these instructions either. At present we don't support v6 so we give a +// warning for unsupported features. + +// CHECK: warning: lld uses extended branch encoding, no object with architecture supporting feature detected. +// CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected.

Don't you want to check that the other warning is not issued?

> +// The ARM support in lld makes some use of instructions that are not available
>  +// on all ARM architectures. Namely:
>  +// - Use of BLX instruction for interworking between ARM and Thumb state.
>  +// - Use of the extended Thumb branch encoding in relocation.
>  +// - Use of the MOVT/MOVW instructions in Thumb Thunks.
>  +// The ARM Attributes section contains information about the architecture chosen
>  +// at compile time. We follow the convention that if at least one input object
>  +// is compiled with an architecture that supports these features then lld is
>  +// permitted to use them.

That is the same heuristic used by bfd and gold?

> +static void updateSupportedARMFeatures(const ARMAttributeParser &Attributes) {
>  +  if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {

Early return maybe?

> +    auto Arch = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
>  +    switch (Arch) {
>  +    case ARMBuildAttrs::Pre_v4:
>  +    case ARMBuildAttrs::v4:
>  +    case ARMBuildAttrs::v4T:
>  +      // Architectures prior to v5 do not support BLX instruction
>  +      break;
>  +    case ARMBuildAttrs::v5T:
>  +    case ARMBuildAttrs::v5TE:
>  +    case ARMBuildAttrs::v5TEJ:
>  +    case ARMBuildAttrs::v6:
>  +    case ARMBuildAttrs::v6KZ:
>  +    case ARMBuildAttrs::v6K:
>  +      Config->ARMHasBlx = true;
>  +      // Architectures used in pre-Cortex processors do not support
>  +      // The https://reviews.llvm.org/J1 = 1 https://reviews.llvm.org/J2 = 1 Thumb branch range extension, with the exception
>  +      // of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do.
>  +      break;
>  +    default:
>  +      // All other Architectures have BLX and extended branch encoding
>  +      Config->ARMHasBlx = true;
>  +      Config->ARMJ1J2BranchEncoding = true;
>  +      if (Arch != ARMBuildAttrs::v6_M && Arch != ARMBuildAttrs::v6S_M)
>  +        // All Architectures used in Cortex processors with the exception
>  +        // of v6-M and v6S-M have the MOVT and MOVW instructions.
>  +        Config->ARMHasMovtMovw = true;
>  +    }
>  +  }

If you invert switch order you can use a fallthrough:

default: //asumed newer than anything listed explicitly.
case newest:

  feature_a = true;

case not_so_new:

  feture_b = true;

...

Not sure if it is actually better. Up to you.

> +}
>  +
> 
>   template <class ELFT>
>   InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
>     uint32_t Idx = Sec.sh_info;
> 
> @@ -381,16 +424,20 @@
> 
>   StringRef Name = getSectionName(Sec);
>   
>   switch (Sec.sh_type) {
> 
> - case SHT_ARM_ATTRIBUTES:
> - // FIXME: ARM meta-data section. Retain the first attribute section
> - // we see. The eglibc ARM dynamic loaders require the presence of an
> - // attribute section for dlopen to work.
> - // In a full implementation we would merge all attribute sections. +  case SHT_ARM_ATTRIBUTES: { +    ARMAttributeParser Attributes; +    ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec)); +    Attributes.Parse(Contents, true);

Add a comment saying what "true" is:

Attributes.Parse(Contents, /*foobar*/ true);

> Index: ELF/Driver.cpp
>  ===================================================================
> 
> - ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1083,6 +1083,28 @@ if (Config->EMachine == EM_MIPS) Config->MipsEFlags = calcMipsEFlags<ELFT>();
> 
>   +  if (Config->EMachine == EM_ARM) { +    if (InX::ARMAttributes == nullptr) { +      // No ARM attributes section present (assembler without .eabi_attribute +      // directives, like lld tests), assume support for all features +      Config->ARMHasBlx = true; +      Config->ARMHasMovtMovw = true; +      Config->ARMJ1J2BranchEncoding = true; +    }

The tests don't fail because of a warning, right? So you could probably
just remove this if.

So LGTM with some nits.

Cheers,
Rafael


https://reviews.llvm.org/D36823





More information about the llvm-commits mailing list