diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2010-12-30 22:59:32 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2010-12-30 22:59:32 +0000 |
commit | c56f847a965ce547b82b1d4471b41d808f80cd4b (patch) | |
tree | fced1aa78b4f7523fb4de578b59d43c693ea0958 /clang/lib/CodeGen/CGStmt.cpp | |
parent | 570dd787a6caf902fc918eff212e35a72662fe58 (diff) | |
download | bcm5719-llvm-c56f847a965ce547b82b1d4471b41d808f80cd4b.tar.gz bcm5719-llvm-c56f847a965ce547b82b1d4471b41d808f80cd4b.zip |
Add support for declaring register contraints in variables. They are only used
in asm statements:
register int foo asm("rdi");
asm("..." : ... "r" (foo) ...
We also only accept these variables if the constraint in the asm statement is "r".
This fixes most of PR3933.
llvm-svn: 122643
Diffstat (limited to 'clang/lib/CodeGen/CGStmt.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 098fe7f4224..1fcafe82e63 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -919,6 +919,32 @@ SimplifyConstraint(const char *Constraint, const TargetInfo &Target, return Result; } +static std::string +AddVariableConstraits(const std::string &Constraint, const Expr &AsmExpr, + const TargetInfo &Target, CodeGenModule &CGM, + const AsmStmt &Stmt) { + const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr); + if (!AsmDeclRef) + return Constraint; + const ValueDecl &Value = *AsmDeclRef->getDecl(); + const VarDecl *Variable = dyn_cast<VarDecl>(&Value); + if (!Variable) + return Constraint; + AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>(); + if (!Attr) + return Constraint; + llvm::StringRef Register = Attr->getLabel(); + if (!Target.isValidGCCRegisterName(Register)) { + CGM.ErrorUnsupported(Variable, "__asm__"); + return Constraint; + } + if (Constraint != "r") { + CGM.ErrorUnsupported(&Stmt, "__asm__"); + return Constraint; + } + return "{" + Register.str() + "}"; +} + llvm::Value* CodeGenFunction::EmitAsmInputLValue(const AsmStmt &S, const TargetInfo::ConstraintInfo &Info, @@ -1056,6 +1082,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { const Expr *OutExpr = S.getOutputExpr(i); OutExpr = OutExpr->IgnoreParenNoopCasts(getContext()); + OutputConstraint = AddVariableConstraits(OutputConstraint, *OutExpr, Target, + CGM, S); + LValue Dest = EmitLValue(OutExpr); if (!Constraints.empty()) Constraints += ','; @@ -1133,6 +1162,11 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target, &OutputConstraintInfos); + InputConstraint = + AddVariableConstraits(InputConstraint, + *InputExpr->IgnoreParenNoopCasts(getContext()), + Target, CGM, S); + llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, Constraints); // If this input argument is tied to a larger output result, extend the |