def ObjC : LangOpt<"ObjC1">;
def BlocksSupported : LangOpt<"Blocks">;
-// Defines targets for target-specific attributes. The list of strings should
-// specify architectures for which the target applies, based off the ArchType
-// enumeration in Triple.h.
-class TargetArch<list<string> arches> {
- list<string> Arches = arches;
+// Defines targets for target-specific attributes. Empty lists are unchecked.
+class TargetSpec {
+ // Specifies Architectures for which the target applies, based off the
+ // ArchType enumeration in Triple.h.
+ list<string> Arches = [];
+ // Specifies Operating Systems for which the target applies, based off the
+ // OSType enumeration in Triple.h
list<string> OSes;
+ // Specifies the C++ ABIs for which the target applies, based off the
+ // TargetCXXABI::Kind in TargetCXXABI.h.
list<string> CXXABIs;
+ // Specifies Object Formats for which the target applies, based off the
+ // ObjectFormatType enumeration in Triple.h
+ list<string> ObjectFormats;
+}
+
+class TargetArch<list<string> arches> : TargetSpec {
+ let Arches = arches;
}
def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
def TargetAVR : TargetArch<["avr"]>;
def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> {
let CXXABIs = ["Microsoft"];
}
+def TargetELF : TargetSpec {
+ let ObjectFormats = ["ELF"];
+}
// Attribute subject match rules that are used for #pragma clang attribute.
//
/// A target-specific attribute. This class is meant to be used as a mixin
/// with InheritableAttr or Attr depending on the attribute's needs.
-class TargetSpecificAttr<TargetArch target> {
- TargetArch Target = target;
+class TargetSpecificAttr<TargetSpec target> {
+ TargetSpec Target = target;
// Attributes are generally required to have unique spellings for their names
// so that the parser can determine what kind of attribute it has parsed.
// However, target-specific attributes are special in that the attribute only
let Documentation = [Undocumented];
}
-def IFunc : Attr {
+def IFunc : Attr, TargetSpecificAttr<TargetELF> {
let Spellings = [GCC<"ifunc">];
let Args = [StringArgument<"Resolver">];
let Subjects = SubjectList<[Function]>;
OS << " }\n";
}
+// Helper function for GenerateTargetSpecificAttrChecks that alters the 'Test'
+// parameter with only a single check type, if applicable.
+static void GenerateTargetSpecificAttrCheck(const Record *R, std::string &Test,
+ std::string *FnName,
+ StringRef ListName,
+ StringRef CheckAgainst,
+ StringRef Scope) {
+ if (!R->isValueUnset(ListName)) {
+ Test += " && (";
+ std::vector<StringRef> Items = R->getValueAsListOfStrings(ListName);
+ for (auto I = Items.begin(), E = Items.end(); I != E; ++I) {
+ StringRef Part = *I;
+ Test += CheckAgainst;
+ Test += " == ";
+ Test += Scope;
+ Test += Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+ }
+}
+
// 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,
// 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) {
- StringRef Part = *I;
- Test += "T.getArch() == llvm::Triple::";
- Test += 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 += "true";
+ // If one or more architectures is specified, check those. Arches are handled
+ // differently because GenerateTargetRequirements needs to combine the list
+ // with ParseKind.
+ if (!Arches.empty()) {
Test += " && (";
- std::vector<StringRef> OSes = R->getValueAsListOfStrings("OSes");
- for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
+ for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
StringRef Part = *I;
-
- Test += "T.getOS() == llvm::Triple::";
+ Test += "T.getArch() == llvm::Triple::";
Test += Part;
if (I + 1 != E)
Test += " || ";
Test += ")";
}
+ // If the attribute is specific to particular OSes, check those.
+ GenerateTargetSpecificAttrCheck(R, Test, FnName, "OSes", "T.getOS()",
+ "llvm::Triple::");
+
// If one or more CXX ABIs are specified, check those as well.
- if (!R->isValueUnset("CXXABIs")) {
- Test += " && (";
- std::vector<StringRef> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
- for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) {
- StringRef Part = *I;
- Test += "Target.getCXXABI().getKind() == TargetCXXABI::";
- Test += Part;
- if (I + 1 != E)
- Test += " || ";
- if (FnName)
- *FnName += Part;
- }
- Test += ")";
- }
+ GenerateTargetSpecificAttrCheck(R, Test, FnName, "CXXABIs",
+ "Target.getCXXABI().getKind()",
+ "TargetCXXABI::");
+ // If one or more object formats is specified, check those.
+ GenerateTargetSpecificAttrCheck(R, Test, FnName, "ObjectFormats",
+ "T.getObjectFormat()", "llvm::Triple::");
}
static void GenerateHasAttrSpellingStringSwitch(
// Get the list of architectures to be tested for.
const Record *R = Attr.getValueAsDef("Target");
std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");
- if (Arches.empty()) {
- PrintError(Attr.getLoc(), "Empty list of target architectures for a "
- "target-specific attr");
- return "defaultTargetRequirements";
- }
// If there are other attributes which share the same parsed attribute kind,
// such as target-specific attributes with a shared spelling, collapse the