Migrate the target attribute parsing code into an extension off of

the main attribute and cache the results so we don't have to parse
a single attribute more than once.

This reapplies r246596 with a fix for an uninitialized class member,
and a couple of cleanups and formatting changes.

llvm-svn: 246610
This commit is contained in:
Eric Christopher 2015-09-02 00:12:02 +00:00
parent e8433cc179
commit bb0cef6e9c
2 changed files with 50 additions and 28 deletions

View File

@ -1315,9 +1315,52 @@ def Pascal : InheritableAttr {
def Target : InheritableAttr {
let Spellings = [GCC<"target">];
let Args = [StringArgument<"features">];
let Args = [StringArgument<"featuresStr">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [TargetDocs];
let AdditionalMembers = [{
StringRef CPU;
std::vector<std::string> Features;
bool Parsed = false;
StringRef getCPU() {
if (!Parsed)
parse();
return CPU;
}
std::vector<std::string> &getFeatures() {
if (!Parsed)
parse();
return Features;
}
void parse() {
SmallVector<StringRef, 1> AttrFeatures;
getFeaturesStr().split(AttrFeatures, ",");
// Grab the various features and prepend a "+" to turn on the feature to
// the backend and add them to our existing set of features.
for (auto &Feature : AttrFeatures) {
// Go ahead and trim whitespace rather than either erroring or
// accepting it weirdly.
Feature = Feature.trim();
// We don't support cpu tuning this way currently.
// TODO: Support the fpmath option. It will require checking
// overall feature validity for the function with the rest of the
// attributes on the function.
if (Feature.startswith("fpmath=") || Feature.startswith("tune="))
continue;
// While we're here iterating check for a different target cpu.
if (Feature.startswith("arch="))
CPU = Feature.split("=").second.trim();
else if (Feature.startswith("no-"))
Features.push_back("-" + Feature.split("-").second.str());
else
Features.push_back("+" + Feature.str());
}
Parsed = true;
}
}];
}
def TransparentUnion : InheritableAttr {

View File

@ -1499,40 +1499,19 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
if (FD && FD->hasAttr<TargetAttr>()) {
llvm::StringMap<bool> FeatureMap;
const auto *TD = FD->getAttr<TargetAttr>();
auto *TD = FD->getAttr<TargetAttr>();
// Make a copy of the features as passed on the command line.
std::vector<std::string> FnFeatures =
getTarget().getTargetOpts().FeaturesAsWritten;
// Grab the target attribute string.
StringRef FeaturesStr = TD->getFeatures();
SmallVector<StringRef, 1> AttrFeatures;
FeaturesStr.split(AttrFeatures, ",");
std::vector<std::string> &AttrFeatures = TD->getFeatures();
std::copy(AttrFeatures.begin(), AttrFeatures.end(),
std::back_inserter(FnFeatures));
// Grab the various features and prepend a "+" to turn on the feature to
// the backend and add them to our existing set of features.
for (auto &Feature : AttrFeatures) {
// Go ahead and trim whitespace rather than either erroring or
// accepting it weirdly.
Feature = Feature.trim();
if (TD->getCPU() != "")
TargetCPU = TD->getCPU();
// While we're here iterating check for a different target cpu.
if (Feature.startswith("arch="))
TargetCPU = Feature.split("=").second.trim();
else if (Feature.startswith("tune="))
// We don't support cpu tuning this way currently.
;
else if (Feature.startswith("fpmath="))
// TODO: Support the fpmath option this way. It will require checking
// overall feature validity for the function with the rest of the
// attributes on the function.
;
else if (Feature.startswith("no-"))
FnFeatures.push_back("-" + Feature.split("-").second.str());
else
FnFeatures.push_back("+" + Feature.str());
}
// Now populate the feature map, first with the TargetCPU which is either
// the default or a new one from the target attribute string. Then we'll
// use the passed in features (FeaturesAsWritten) along with the new ones