-
Notifications
You must be signed in to change notification settings - Fork 15.4k
RFC: Implementing new mechanism for hard register operands to inline asm as a constraint. #85846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -831,6 +831,18 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { | |
| case 'E': | ||
| case 'F': | ||
| break; // Pass them. | ||
| case '{': { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's unclear to me whether this uses the same register parsing logic as the existing named-register asm on variables. It looks like it's going to do something different, which worries me. I think we ought to be accepting the exact same names in both syntaxes, on all platforms. Can you confirm if that's actually the case with this PR?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we should be using the same names. The register asm variable is parsed in |
||
| // First, check the target parser in case it validates | ||
| // the {...} constraint differently. | ||
| if (validateAsmConstraint(Name, Info)) | ||
| return true; | ||
|
|
||
| // If not, that's okay, we will try to validate it | ||
| // using a target agnostic implementation. | ||
| if (!validateHardRegisterAsmConstraint(Name, Info)) | ||
| return false; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| Name++; | ||
|
|
@@ -846,6 +858,36 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { | |
| return Info.allowsMemory() || Info.allowsRegister(); | ||
| } | ||
|
|
||
| bool TargetInfo::validateHardRegisterAsmConstraint( | ||
| const char *&Name, TargetInfo::ConstraintInfo &Info) const { | ||
| // First, swallow the '{'. | ||
| Name++; | ||
|
|
||
| // Mark the start of the possible register name. | ||
| const char *Start = Name; | ||
|
|
||
| // Loop through rest of "Name". | ||
| // In this loop, we check whether we have a closing curly brace which | ||
| // validates the constraint. Also, this allows us to get the correct bounds to | ||
| // set our register name. | ||
| while (*Name && *Name != '}') | ||
| Name++; | ||
|
|
||
| // Missing '}' or if there is anything after '}', return false. | ||
| if (!*Name || *(Name + 1)) | ||
| return false; | ||
|
|
||
| // Now we set the register name. | ||
| std::string Register(Start, Name - Start); | ||
|
|
||
| // We validate whether its a valid register to be used. | ||
| if (!isValidGCCRegisterName(Register)) | ||
| return false; | ||
|
|
||
| Info.setAllowsRegister(); | ||
| return true; | ||
| } | ||
|
|
||
| bool TargetInfo::resolveSymbolicName(const char *&Name, | ||
| ArrayRef<ConstraintInfo> OutputConstraints, | ||
| unsigned &Index) const { | ||
|
|
@@ -978,6 +1020,18 @@ bool TargetInfo::validateInputConstraint( | |
| case '!': // Disparage severely. | ||
| case '*': // Ignore for choosing register preferences. | ||
| break; // Pass them. | ||
| case '{': { | ||
| // First, check the target parser in case it validates | ||
| // the {...} constraint differently. | ||
| if (validateAsmConstraint(Name, Info)) | ||
| return true; | ||
|
|
||
| // If not, that's okay, we will try to validate it | ||
| // using a target agnostic implementation. | ||
| if (!validateHardRegisterAsmConstraint(Name, Info)) | ||
| return false; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| Name++; | ||
|
|
@@ -1059,6 +1113,14 @@ void TargetInfo::copyAuxTarget(const TargetInfo *Aux) { | |
| std::string | ||
| TargetInfo::simplifyConstraint(StringRef Constraint, | ||
| SmallVectorImpl<ConstraintInfo> *OutCons) const { | ||
| // If we have only the {...} constraint, do not do any simplifications. This | ||
| // already maps to the lower level LLVM inline assembly IR that tells the | ||
| // backend to allocate a specific register. Any validations would have already | ||
| // been done in the Sema stage or will be done in the AddVariableConstraints | ||
| // function. | ||
| if (Constraint[0] == '{' || (Constraint[0] == '&' && Constraint[1] == '{')) | ||
| return std::string(Constraint); | ||
|
|
||
| std::string Result; | ||
|
|
||
| for (const char *I = Constraint.begin(), *E = Constraint.end(); I < E; I++) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.