aboutsummaryrefslogtreecommitdiff
path: root/lib/Basic/TargetInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/TargetInfo.cpp')
-rw-r--r--lib/Basic/TargetInfo.cpp37
1 files changed, 32 insertions, 5 deletions
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index aecf13b00854..6987cd71f3d7 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -338,6 +338,8 @@ bool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
// Get rid of any register prefix.
Name = removeGCCRegisterPrefix(Name);
+ if (Name.empty())
+ return false;
getGCCRegNames(Names, NumNames);
@@ -457,7 +459,9 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
// Eventually, an unknown constraint should just be treated as 'g'.
return false;
}
+ break;
case '&': // early clobber.
+ Info.setEarlyClobber();
break;
case '%': // commutative.
// FIXME: Check that there is a another register after this one.
@@ -482,9 +486,12 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
if (Name[1] == '=' || Name[1] == '+')
Name++;
break;
+ case '#': // Ignore as constraint.
+ while (Name[1] && Name[1] != ',')
+ Name++;
+ break;
case '?': // Disparage slightly code.
case '!': // Disparage severely.
- case '#': // Ignore as constraint.
case '*': // Ignore for choosing register preferences.
break; // Pass them.
}
@@ -492,6 +499,11 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
Name++;
}
+ // Early clobber with a read-write constraint which doesn't permit registers
+ // is invalid.
+ if (Info.earlyClobber() && Info.isReadWrite() && !Info.allowsRegister())
+ return false;
+
// If a constraint allows neither memory nor register operands it contains
// only modifiers. Reject it.
return Info.allowsMemory() || Info.allowsRegister();
@@ -534,11 +546,17 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
default:
// Check if we have a matching constraint
if (*Name >= '0' && *Name <= '9') {
- unsigned i = *Name - '0';
+ const char *DigitStart = Name;
+ while (Name[1] >= '0' && Name[1] <= '9')
+ Name++;
+ const char *DigitEnd = Name;
+ unsigned i;
+ if (StringRef(DigitStart, DigitEnd - DigitStart + 1)
+ .getAsInteger(10, i))
+ return false;
// Check if matching constraint is out of bounds.
- if (i >= NumOutputs)
- return false;
+ if (i >= NumOutputs) return false;
// A number must refer to an output only operand.
if (OutputConstraints[i].isReadWrite())
@@ -569,6 +587,10 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
return false;
+ // A number must refer to an output only operand.
+ if (OutputConstraints[Index].isReadWrite())
+ return false;
+
Info.setTiedOperand(Index, OutputConstraints[Index]);
break;
}
@@ -586,6 +608,8 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
case 'N':
case 'O':
case 'P':
+ if (!validateAsmConstraint(Name, Info))
+ return false;
break;
case 'r': // general register.
Info.setAllowsRegister();
@@ -608,9 +632,12 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
break;
case ',': // multiple alternative constraint. Ignore comma.
break;
+ case '#': // Ignore as constraint.
+ while (Name[1] && Name[1] != ',')
+ Name++;
+ break;
case '?': // Disparage slightly code.
case '!': // Disparage severely.
- case '#': // Ignore as constraint.
case '*': // Ignore for choosing register preferences.
break; // Pass them.
}