Add more semantic analysis for inline asm statements.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44349 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Basic/TargetInfo.cpp b/Basic/TargetInfo.cpp
index 3b20d3a..ec91bdd 100644
--- a/Basic/TargetInfo.cpp
+++ b/Basic/TargetInfo.cpp
@@ -314,3 +314,127 @@
return false;
}
+
+const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const
+{
+ assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
+
+ const char * const *Names;
+ unsigned NumNames;
+
+ PrimaryTarget->getGCCRegNames(Names, NumNames);
+
+ // First, check if we have a number.
+ if (isdigit(Name[0])) {
+ char *End;
+ int n = (int)strtol(Name, &End, 0);
+ if (*End == 0) {
+ assert(n >= 0 && (unsigned)n < NumNames &&
+ "Out of bounds register number!");
+ return Names[n];
+ }
+ }
+
+ // Now check aliases.
+ const TargetInfoImpl::GCCRegAlias *Aliases;
+ unsigned NumAliases;
+
+ PrimaryTarget->getGCCRegAliases(Aliases, NumAliases);
+ for (unsigned i = 0; i < NumAliases; i++) {
+ for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
+ if (!Aliases[i].Aliases[j])
+ break;
+ if (strcmp(Aliases[i].Aliases[j], Name) == 0)
+ return Aliases[i].Register;
+ }
+ }
+
+ return Name;
+}
+
+bool TargetInfo::validateOutputConstraint(const char *Name,
+ ConstraintInfo &info) const
+{
+ // An output constraint must start with '=' or '+'
+ if (*Name != '=' && *Name != '+')
+ return false;
+
+ if (*Name == '+')
+ info = CI_ReadWrite;
+ else
+ info = CI_None;
+
+ Name++;
+ while (*Name) {
+ switch (*Name) {
+ default:
+ if (!PrimaryTarget->validateAsmConstraint(*Name, info)) {
+ // FIXME: This assert is in place temporarily
+ // so we can add more constraints as we hit it.
+ // Eventually, an unknown constraint should just be treated as 'g'.
+ assert(0 && "Unknown output constraint type!");
+ }
+ case '&': // early clobber.
+ break;
+ case 'r': // general register.
+ info = (ConstraintInfo)(info|CI_AllowsRegister);
+ break;
+ case 'm': // memory operand.
+ info = (ConstraintInfo)(info|CI_AllowsMemory);
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
+ break;
+ }
+
+ Name++;
+ }
+
+ return true;
+}
+
+bool TargetInfo::validateInputConstraint(const char *Name,
+ unsigned NumOutputs,
+ ConstraintInfo &info) const
+{
+ while (*Name) {
+ switch (*Name) {
+ default:
+ // Check if we have a matching constraint
+ if (*Name >= '0' && *Name <= '9') {
+ unsigned i = *Name - '0';
+
+ // Check if matching constraint is out of bounds.
+ if (i >= NumOutputs)
+ return false;
+ } else if (!PrimaryTarget->validateAsmConstraint(*Name, info)) {
+ // FIXME: This assert is in place temporarily
+ // so we can add more constraints as we hit it.
+ // Eventually, an unknown constraint should just be treated as 'g'.
+ assert(0 && "Unknown input constraint type!");
+ }
+ case 'i': // immediate integer.
+ break;
+ case 'r': // general register.
+ info = (ConstraintInfo)(info|CI_AllowsRegister);
+ break;
+ case 'm': // memory operand.
+ info = (ConstraintInfo)(info|CI_AllowsMemory);
+ break;
+ case 'g': // general register, memory operand or immediate integer.
+ info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
+ break;
+ }
+
+ Name++;
+ }
+
+ return true;
+}
+
+const char *TargetInfo::getClobbers() const
+{
+ return PrimaryTarget->getClobbers();
+}
+
+