// Checks if there is a conflict between the input and output lists with the // clobbers list. If there's a conflict, returns the location of the // conflicted clobber, else returns nullptr static SourceLocation getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints, StringLiteral **Clobbers, int NumClobbers, const TargetInfo &Target, ASTContext &Cont) { llvm::StringSet<> InOutVars; // Collect all the input and output registers from the extended asm // statement in order to check for conflicts with the clobber list for (unsigned int i = 0; i < Exprs.size(); ++i) { StringRef Constraint = Constraints[i]->getString(); StringRef InOutReg = Target.getConstraintRegister( Constraint, extractRegisterName(Exprs[i], Target)); if (InOutReg != "") InOutVars.insert(InOutReg); } // Check for each item in the clobber list if it conflicts with the input // or output for (int i = 0; i < NumClobbers; ++i) { StringRef Clobber = Clobbers[i]->getString(); // We only check registers, therefore we don't check cc and memory // clobbers if (Clobber == "cc" || Clobber == "memory") continue; Clobber = Target.getNormalizedGCCRegisterName(Clobber, true); // Go over the output's registers we collected if (InOutVars.count(Clobber)) return Clobbers[i]->getLocStart(); } return SourceLocation(); }
// Extracting the register name from the Expression value, // if there is no register name to extract, returns "" static StringRef extractRegisterName(const Expr *Expression, const TargetInfo &Target) { Expression = Expression->IgnoreImpCasts(); if (const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(Expression)) { // Handle cases where the expression is a variable const VarDecl *Variable = dyn_cast<VarDecl>(AsmDeclRef->getDecl()); if (Variable && Variable->getStorageClass() == SC_Register) { if (AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>()) if (Target.isValidGCCRegisterName(Attr->getLabel())) return Target.getNormalizedGCCRegisterName(Attr->getLabel(), true); } } return ""; }