r242731 - Refactor TableGen backend for ClangAttrEmitter to avoid duplication.

Aaron Ballman aaron at aaronballman.com
Tue Jul 21 05:22:55 PDT 2015


On Mon, Jul 20, 2015 at 6:57 PM, Bob Wilson <bob.wilson at apple.com> wrote:
> Author: bwilson
> Date: Mon Jul 20 17:57:36 2015
> New Revision: 242731
>
> URL: http://llvm.org/viewvc/llvm-project?rev=242731&view=rev
> Log:
> Refactor TableGen backend for ClangAttrEmitter to avoid duplication.
>
> GenerateHasAttrSpellingStringSwitch and GenerateTargetRequirements had
> duplicated code to check the conditions for target-specific attributes.
> Refactor the duplicated code into a separate function. NFC.

Thank you for this!

~Aaron

>
> Modified:
>     cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
>
> Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=242731&r1=242730&r2=242731&view=diff
> ==============================================================================
> --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
> +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Jul 20 17:57:36 2015
> @@ -1860,6 +1860,65 @@ void EmitClangAttrPCHWrite(RecordKeeper
>    OS << "  }\n";
>  }
>
> +// Generate a conditional expression to check if the current target satisfies
> +// the conditions for a TargetSpecificAttr record, and append the code for
> +// those checks to the Test string. If the FnName string pointer is non-null,
> +// append a unique suffix to distinguish this set of target checks from other
> +// TargetSpecificAttr records.
> +static void GenerateTargetSpecificAttrChecks(const Record *R,
> +                                             std::vector<std::string> &Arches,
> +                                             std::string &Test,
> +                                             std::string *FnName) {
> +  // It is assumed that there will be an llvm::Triple object
> +  // named "T" and a TargetInfo object named "Target" within
> +  // scope that can be used to determine whether the attribute exists in
> +  // a given target.
> +  Test += "(";
> +
> +  for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
> +    std::string Part = *I;
> +    Test += "T.getArch() == llvm::Triple::" + Part;
> +    if (I + 1 != E)
> +      Test += " || ";
> +    if (FnName)
> +      *FnName += Part;
> +  }
> +  Test += ")";
> +
> +  // If the attribute is specific to particular OSes, check those.
> +  if (!R->isValueUnset("OSes")) {
> +    // We know that there was at least one arch test, so we need to and in the
> +    // OS tests.
> +    Test += " && (";
> +    std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
> +    for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
> +      std::string Part = *I;
> +
> +      Test += "T.getOS() == llvm::Triple::" + Part;
> +      if (I + 1 != E)
> +        Test += " || ";
> +      if (FnName)
> +        *FnName += Part;
> +    }
> +    Test += ")";
> +  }
> +
> +  // If one or more CXX ABIs are specified, check those as well.
> +  if (!R->isValueUnset("CXXABIs")) {
> +    Test += " && (";
> +    std::vector<std::string> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
> +    for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) {
> +      std::string Part = *I;
> +      Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part;
> +      if (I + 1 != E)
> +        Test += " || ";
> +      if (FnName)
> +        *FnName += Part;
> +    }
> +    Test += ")";
> +  }
> +}
> +
>  static void GenerateHasAttrSpellingStringSwitch(
>      const std::vector<Record *> &Attrs, raw_ostream &OS,
>      const std::string &Variety = "", const std::string &Scope = "") {
> @@ -1885,53 +1944,11 @@ static void GenerateHasAttrSpellingStrin
>        }
>      }
>
> -    // It is assumed that there will be an llvm::Triple object
> -    // named "T" and a TargetInfo object named "Target" within
> -    // scope that can be used to determine whether the attribute exists in
> -    // a given target.
>      std::string Test;
>      if (Attr->isSubClassOf("TargetSpecificAttr")) {
>        const Record *R = Attr->getValueAsDef("Target");
>        std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
> -
> -      Test += "(";
> -      for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
> -        std::string Part = *AI;
> -        Test += "T.getArch() == llvm::Triple::" + Part;
> -        if (AI + 1 != AE)
> -          Test += " || ";
> -      }
> -      Test += ")";
> -
> -      // If the attribute is specific to particular OSes, check those.
> -      std::vector<std::string> OSes;
> -      if (!R->isValueUnset("OSes")) {
> -        Test += " && (";
> -        std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
> -        for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
> -          std::string Part = *AI;
> -
> -          Test += "T.getOS() == llvm::Triple::" + Part;
> -          if (AI + 1 != AE)
> -            Test += " || ";
> -        }
> -        Test += ")";
> -      }
> -
> -      // If one or more CXX ABIs are specified, check those as well.
> -      if (!R->isValueUnset("CXXABIs")) {
> -        Test += " && (";
> -        std::vector<std::string> CXXABIs =
> -          R->getValueAsListOfStrings("CXXABIs");
> -        for (auto AI = CXXABIs.begin(), AE = CXXABIs.end(); AI != AE; ++AI) {
> -          std::string Part = *AI;
> -
> -          Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part;
> -          if (AI + 1 != AE)
> -            Test += " || ";
> -        }
> -        Test += ")";
> -      }
> +      GenerateTargetSpecificAttrChecks(R, Arches, Test, 0);
>
>        // If this is the C++11 variety, also add in the LangOpts test.
>        if (Variety == "CXX11")
> @@ -2521,49 +2538,9 @@ static std::string GenerateTargetRequire
>      }
>    }
>
> -  std::string FnName = "isTarget", Test = "(";
> -  for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
> -    std::string Part = *I;
> -    Test += "Arch == llvm::Triple::" + Part;
> -    if (I + 1 != E)
> -      Test += " || ";
> -    FnName += Part;
> -  }
> -  Test += ")";
> -
> -  // If the target also requires OS testing, generate those tests as well.
> -  bool UsesOS = false;
> -  if (!R->isValueUnset("OSes")) {
> -    UsesOS = true;
> -
> -    // We know that there was at least one arch test, so we need to and in the
> -    // OS tests.
> -    Test += " && (";
> -    std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
> -    for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
> -      std::string Part = *I;
> -
> -      Test += "OS == llvm::Triple::" + Part;
> -      if (I + 1 != E)
> -        Test += " || ";
> -      FnName += Part;
> -    }
> -    Test += ")";
> -  }
> -
> -  // Test for the C++ ABI, if specified.
> -  if (!R->isValueUnset("CXXABIs")) {
> -    Test += " && (";
> -    std::vector<std::string> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
> -    for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) {
> -      std::string Part = *I;
> -      Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part;
> -      if (I + 1 != E)
> -        Test += " || ";
> -      FnName += Part;
> -    }
> -    Test += ")";
> -  }
> +  std::string FnName = "isTarget";
> +  std::string Test;
> +  GenerateTargetSpecificAttrChecks(R, Arches, Test, &FnName);
>
>    // If this code has already been generated, simply return the previous
>    // instance of it.
> @@ -2574,9 +2551,6 @@ static std::string GenerateTargetRequire
>
>    OS << "static bool " << FnName << "(const TargetInfo &Target) {\n";
>    OS << "  const llvm::Triple &T = Target.getTriple();\n";
> -  OS << "  llvm::Triple::ArchType Arch = T.getArch();\n";
> -  if (UsesOS)
> -    OS << "  llvm::Triple::OSType OS = T.getOS();\n";
>    OS << "  return " << Test << ";\n";
>    OS << "}\n\n";
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list