diff options
Diffstat (limited to 'lib/Basic/TargetInfo.cpp')
-rw-r--r-- | lib/Basic/TargetInfo.cpp | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index aecf13b..6987cd7 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. } |