@@ -2471,36 +2471,151 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
24712471 CaseRangeBlock = SavedCRBlock;
24722472}
24732473
2474- // / AddVariableConstraints - Look at AsmExpr and if it is a variable declared
2475- // / as using a particular register add that as a constraint that will be used
2476- // / in this asm stmt.
2477- static std::string
2478- AddVariableConstraints (const std::string &Constraint, const Expr &AsmExpr,
2479- const TargetInfo &Target, CodeGenModule &CGM,
2480- const AsmStmt &Stmt, const bool EarlyClobber,
2481- std::string *GCCReg = nullptr ) {
2474+ static std::string SimplifyConstraint (
2475+ const char *Constraint, const TargetInfo &Target,
2476+ SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons = nullptr ) {
2477+ // If we have only the {...} constraint, do not do any simplifications. This
2478+ // already maps to the lower level LLVM inline assembly IR that tells the
2479+ // backend to allocate a specific register. Any validations would have already
2480+ // been done in the Sema stage or will be done in the AddVariableConstraints
2481+ // function.
2482+ if (Constraint[0 ] == ' {' || (Constraint[0 ] == ' &' && Constraint[1 ] == ' {' ))
2483+ return std::string (Constraint);
2484+
2485+ std::string Result;
2486+
2487+ while (*Constraint) {
2488+ switch (*Constraint) {
2489+ default :
2490+ Result += Target.convertConstraint (Constraint);
2491+ break ;
2492+ // Ignore these
2493+ case ' *' :
2494+ case ' ?' :
2495+ case ' !' :
2496+ case ' =' : // Will see this and the following in mult-alt constraints.
2497+ case ' +' :
2498+ break ;
2499+ case ' #' : // Ignore the rest of the constraint alternative.
2500+ while (Constraint[1 ] && Constraint[1 ] != ' ,' )
2501+ Constraint++;
2502+ break ;
2503+ case ' &' :
2504+ case ' %' :
2505+ Result += *Constraint;
2506+ while (Constraint[1 ] && Constraint[1 ] == *Constraint)
2507+ Constraint++;
2508+ break ;
2509+ case ' ,' :
2510+ Result += " |" ;
2511+ break ;
2512+ case ' g' :
2513+ Result += " imr" ;
2514+ break ;
2515+ case ' [' : {
2516+ assert (OutCons &&
2517+ " Must pass output names to constraints with a symbolic name" );
2518+ unsigned Index;
2519+ bool result = Target.resolveSymbolicName (Constraint, *OutCons, Index);
2520+ assert (result && " Could not resolve symbolic name" ); (void )result;
2521+ Result += llvm::utostr (Index);
2522+ break ;
2523+ }
2524+ }
2525+
2526+ Constraint++;
2527+ }
2528+
2529+ return Result;
2530+ }
2531+ // / Is it valid to apply a register constraint for a variable marked with
2532+ // / the "register asm" construct?
2533+ // / Optionally, if it is determined that we can, we set "Register" to the
2534+ // / regiser name.
2535+ static bool
2536+ ShouldApplyRegisterVariableConstraint (const Expr &AsmExpr,
2537+ std::string *Register = nullptr ) {
2538+
24822539 const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
24832540 if (!AsmDeclRef)
2484- return Constraint ;
2541+ return false ;
24852542 const ValueDecl &Value = *AsmDeclRef->getDecl ();
24862543 const VarDecl *Variable = dyn_cast<VarDecl>(&Value);
24872544 if (!Variable)
2488- return Constraint ;
2545+ return false ;
24892546 if (Variable->getStorageClass () != SC_Register)
2490- return Constraint ;
2547+ return false ;
24912548 AsmLabelAttr *Attr = Variable->getAttr <AsmLabelAttr>();
24922549 if (!Attr)
2550+ return false ;
2551+
2552+ if (Register != nullptr )
2553+ // Set the register to return from Attr.
2554+ *Register = Attr->getLabel ().str ();
2555+ return true ;
2556+ }
2557+
2558+ // / AddVariableConstraints:
2559+ // / Look at AsmExpr and if it is a variable declared as using a particular
2560+ // / register add that as a constraint that will be used in this asm stmt.
2561+ // / Whether it can be used or not is dependent on querying
2562+ // / ShouldApplyRegisterVariableConstraint() Also check whether the "hard
2563+ // / register" inline asm constraint (i.e. "{reg-name}") is specified. If so, add
2564+ // / that as a constraint that will be used in this asm stmt.
2565+ static std::string
2566+ AddVariableConstraints (const std::string &Constraint, const Expr &AsmExpr,
2567+ const TargetInfo &Target, CodeGenModule &CGM,
2568+ const AsmStmt &Stmt, const bool EarlyClobber,
2569+ std::string *GCCReg = nullptr ) {
2570+
2571+ // Do we have the "hard register" inline asm constraint.
2572+ bool ApplyHardRegisterConstraint =
2573+ Constraint[0 ] == ' {' || (EarlyClobber && Constraint[1 ] == ' {' );
2574+
2575+ // Do we have "register asm" on a variable.
2576+ std::string Reg = " " ;
2577+ bool ApplyRegisterVariableConstraint =
2578+ ShouldApplyRegisterVariableConstraint (AsmExpr, &Reg);
2579+
2580+ // Diagnose the scenario where we apply both the register variable constraint
2581+ // and a hard register variable constraint as an unsupported error.
2582+ // Why? Because we could have a situation where the register passed in through
2583+ // {...} and the register passed in through the "register asm" construct could
2584+ // be different, and in this case, there's no way for the compiler to know
2585+ // which one to emit.
2586+ if (ApplyHardRegisterConstraint && ApplyRegisterVariableConstraint) {
2587+ CGM.getDiags ().Report (AsmExpr.getExprLoc (),
2588+ diag::err_asm_hard_reg_variable_duplicate);
24932589 return Constraint;
2494- StringRef Register = Attr->getLabel ();
2495- assert (Target.isValidGCCRegisterName (Register));
2590+ }
2591+
2592+ if (!ApplyHardRegisterConstraint && !ApplyRegisterVariableConstraint)
2593+ return Constraint;
2594+
24962595 // We're using validateOutputConstraint here because we only care if
24972596 // this is a register constraint.
24982597 TargetInfo::ConstraintInfo Info (Constraint, " " );
2499- if (Target.validateOutputConstraint (Info) &&
2500- !Info.allowsRegister ()) {
2598+ if (Target.validateOutputConstraint (Info) && !Info.allowsRegister ()) {
25012599 CGM.ErrorUnsupported (&Stmt, " __asm__" );
25022600 return Constraint;
25032601 }
2602+
2603+ if (ApplyHardRegisterConstraint) {
2604+ int Start = EarlyClobber ? 2 : 1 ;
2605+ int End = Constraint.find (' }' );
2606+ Reg = Constraint.substr (Start, End - Start);
2607+ // If we don't have a valid register name, simply return the constraint.
2608+ // For example: There are some targets like X86 that use a constraint such
2609+ // as "@cca", which is validated and then converted into {@cca}. Now this
2610+ // isn't necessarily a "GCC Register", but in terms of emission, it is
2611+ // valid since it lowered appropriately in the X86 backend. For the {..}
2612+ // constraint, we shouldn't be too strict and error out if the register
2613+ // itself isn't a valid "GCC register".
2614+ if (!Target.isValidGCCRegisterName (Reg))
2615+ return Constraint;
2616+ }
2617+
2618+ StringRef Register (Reg);
25042619 // Canonicalize the register here before returning it.
25052620 Register = Target.getNormalizedGCCRegisterName (Register);
25062621 if (GCCReg != nullptr )
0 commit comments