[inline-asm]No error for conflict between inputs\outputs and clobber … · llvm/llvm-project@c42fd03 (original) (raw)
`@@ -22,6 +22,7 @@
`
22
22
`#include "clang/Sema/ScopeInfo.h"
`
23
23
`#include "clang/Sema/SemaInternal.h"
`
24
24
`#include "llvm/ADT/ArrayRef.h"
`
``
25
`+
#include "llvm/ADT/StringSet.h"
`
25
26
`#include "llvm/MC/MCParser/MCAsmParser.h"
`
26
27
`using namespace clang;
`
27
28
`using namespace sema;
`
`@@ -137,6 +138,57 @@ static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
`
137
138
`return false;
`
138
139
`}
`
139
140
``
``
141
`+
// Extracting the register name from the Expression value,
`
``
142
`+
// if there is no register name to extract, returns ""
`
``
143
`+
static StringRef extractRegisterName(const Expr *Expression,
`
``
144
`+
const TargetInfo &Target) {
`
``
145
`+
Expression = Expression->IgnoreImpCasts();
`
``
146
`+
if (const DeclRefExpr *AsmDeclRef = dyn_cast(Expression)) {
`
``
147
`+
// Handle cases where the expression is a variable
`
``
148
`+
const VarDecl *Variable = dyn_cast(AsmDeclRef->getDecl());
`
``
149
`+
if (Variable && Variable->getStorageClass() == SC_Register) {
`
``
150
`+
if (AsmLabelAttr *Attr = Variable->getAttr())
`
``
151
`+
if (Target.isValidGCCRegisterName(Attr->getLabel()))
`
``
152
`+
return Target.getNormalizedGCCRegisterName(Attr->getLabel(), true);
`
``
153
`+
}
`
``
154
`+
}
`
``
155
`+
return "";
`
``
156
`+
}
`
``
157
+
``
158
`+
// Checks if there is a conflict between the input and output lists with the
`
``
159
`+
// clobbers list. If there's a conflict, returns the location of the
`
``
160
`+
// conflicted clobber, else returns nullptr
`
``
161
`+
static SourceLocation
`
``
162
`+
getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
`
``
163
`+
StringLiteral **Clobbers, int NumClobbers,
`
``
164
`+
const TargetInfo &Target, ASTContext &Cont) {
`
``
165
`+
llvm::StringSet<> InOutVars;
`
``
166
`+
// Collect all the input and output registers from the extended asm
`
``
167
`+
// statement
`
``
168
`+
// in order to check for conflicts with the clobber list
`
``
169
`+
for (int i = 0; i < Exprs.size(); ++i) {
`
``
170
`+
StringRef Constraint = Constraints[i]->getString();
`
``
171
`+
StringRef InOutReg = Target.getConstraintRegister(
`
``
172
`+
Constraint, extractRegisterName(Exprs[i], Target));
`
``
173
`+
if (InOutReg != "")
`
``
174
`+
InOutVars.insert(InOutReg);
`
``
175
`+
}
`
``
176
`+
// Check for each item in the clobber list if it conflicts with the input
`
``
177
`+
// or output
`
``
178
`+
for (int i = 0; i < NumClobbers; ++i) {
`
``
179
`+
StringRef Clobber = Clobbers[i]->getString();
`
``
180
`+
// We only check registers, therefore we don't check cc and memory
`
``
181
`+
// clobbers
`
``
182
`+
if (Clobber == "cc" || Clobber == "memory")
`
``
183
`+
continue;
`
``
184
`+
Clobber = Target.getNormalizedGCCRegisterName(Clobber, true);
`
``
185
`+
// Go over the output's registers we collected
`
``
186
`+
if (InOutVars.count(Clobber))
`
``
187
`+
return Clobbers[i]->getLocStart();
`
``
188
`+
}
`
``
189
`+
return SourceLocation();
`
``
190
`+
}
`
``
191
+
140
192
`StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
`
141
193
`bool IsVolatile, unsigned NumOutputs,
`
142
194
`unsigned NumInputs, IdentifierInfo **Names,
`
`@@ -543,6 +595,13 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
`
543
595
`return StmtError();
`
544
596
` }
`
545
597
``
``
598
`+
// Check for conflicts between clobber list and input or output lists
`
``
599
`+
SourceLocation ConstraintLoc =
`
``
600
`+
getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers,
`
``
601
`+
Context.getTargetInfo(), Context);
`
``
602
`+
if (ConstraintLoc.isValid())
`
``
603
`+
return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
`
``
604
+
546
605
`return NS;
`
547
606
`}
`
548
607
``