From: Chris Lattner Date: Sun, 26 Apr 2009 07:16:29 +0000 (+0000) Subject: change TargetInfo::ConstraintInfo to be a struct that contains X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=44def070435a2b5d67f0534f7a3a85a7389d60f2;p=clang change TargetInfo::ConstraintInfo to be a struct that contains the enum along with some other data. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70114 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 96811f0e60..04a4b228f7 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -198,11 +198,31 @@ public: // For example, on x86 it will return "ax" when "eax" is passed in. const char *getNormalizedGCCRegisterName(const char *Name) const; - enum ConstraintInfo { - CI_None = 0x00, - CI_AllowsMemory = 0x01, - CI_AllowsRegister = 0x02, - CI_ReadWrite = 0x04 + struct ConstraintInfo { + enum { + CI_None = 0x00, + CI_AllowsMemory = 0x01, + CI_AllowsRegister = 0x02, + CI_ReadWrite = 0x04 // "+r" output constraint (read and write). + }; + unsigned Flags; + int TiedOperand; + public: + ConstraintInfo() : Flags(0), TiedOperand(-1) {} + + bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; } + bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; } + bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; } + bool hasTiedOperand() const { return TiedOperand != -1; } + unsigned getTiedOperand() const { + assert(hasTiedOperand() && "Has no tied operand!"); + return (unsigned)TiedOperand; + } + + void setIsReadWrite() { Flags |= CI_ReadWrite; } + void setAllowsMemory() { Flags |= CI_AllowsMemory; } + void setAllowsRegister() { Flags |= CI_AllowsRegister; } + void setTiedOperand(unsigned N) { TiedOperand = N; } }; // validateOutputConstraint, validateInputConstraint - Checks that diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index b66e26f3a9..cee13eab41 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -164,24 +164,19 @@ const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const { } bool TargetInfo::validateOutputConstraint(const char *Name, - ConstraintInfo &info) const -{ - info = CI_None; - + ConstraintInfo &Info) const { // An output constraint must start with '=' or '+' if (*Name != '=' && *Name != '+') return false; if (*Name == '+') - info = CI_ReadWrite; - else - info = CI_None; + Info.setIsReadWrite(); Name++; while (*Name) { switch (*Name) { default: - if (!validateAsmConstraint(Name, info)) { + if (!validateAsmConstraint(Name, Info)) { // FIXME: We temporarily return false // so we can add more constraints as we hit it. // Eventually, an unknown constraint should just be treated as 'g'. @@ -190,14 +185,15 @@ bool TargetInfo::validateOutputConstraint(const char *Name, case '&': // early clobber. break; case 'r': // general register. - info = (ConstraintInfo)(info|CI_AllowsRegister); + Info.setAllowsRegister(); break; case 'm': // memory operand. - info = (ConstraintInfo)(info|CI_AllowsMemory); + Info.setAllowsMemory(); break; case 'g': // general register, memory operand or immediate integer. case 'X': // any operand. - info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister); + Info.setAllowsRegister(); + Info.setAllowsMemory(); break; } @@ -210,10 +206,8 @@ bool TargetInfo::validateOutputConstraint(const char *Name, bool TargetInfo::resolveSymbolicName(const char *&Name, const std::string *OutputNamesBegin, const std::string *OutputNamesEnd, - unsigned &Index) const -{ + unsigned &Index) const { assert(*Name == '[' && "Symbolic name did not start with '['"); - Name++; const char *Start = Name; while (*Name && *Name != ']') @@ -240,10 +234,8 @@ bool TargetInfo::resolveSymbolicName(const char *&Name, bool TargetInfo::validateInputConstraint(const char *Name, const std::string *OutputNamesBegin, const std::string *OutputNamesEnd, - ConstraintInfo* OutputConstraints, - ConstraintInfo &info) const { - info = CI_None; - + ConstraintInfo *OutputConstraints, + ConstraintInfo &Info) const { while (*Name) { switch (*Name) { default: @@ -258,8 +250,9 @@ bool TargetInfo::validateInputConstraint(const char *Name, // The constraint should have the same info as the respective // output constraint. - info = (ConstraintInfo)(info|OutputConstraints[i]); - } else if (!validateAsmConstraint(Name, info)) { + Info = OutputConstraints[i]; + Info.setTiedOperand(i); + } else if (!validateAsmConstraint(Name, Info)) { // FIXME: This error return is in place temporarily so we can // add more constraints as we hit it. Eventually, an unknown // constraint should just be treated as 'g'. @@ -281,14 +274,15 @@ bool TargetInfo::validateInputConstraint(const char *Name, case 'n': // immediate integer with a known value. break; case 'r': // general register. - info = (ConstraintInfo)(info|CI_AllowsRegister); + Info.setAllowsRegister(); break; case 'm': // memory operand. - info = (ConstraintInfo)(info|CI_AllowsMemory); + Info.setAllowsMemory(); break; case 'g': // general register, memory operand or immediate integer. case 'X': // any operand. - info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister); + Info.setAllowsRegister(); + Info.setAllowsMemory(); break; } diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index cb74001078..98f6dc1af0 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -280,14 +280,14 @@ public: virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, unsigned &NumAliases) const; virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + TargetInfo::ConstraintInfo &Info) const { switch (*Name) { default: return false; case 'O': // Zero return true; case 'b': // Base register case 'f': // Floating point register - info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister); + Info.setAllowsRegister(); return true; } } @@ -638,7 +638,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, bool X86TargetInfo::validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + TargetInfo::ConstraintInfo &Info) const { switch (*Name) { default: return false; case 'a': // eax. @@ -660,7 +660,7 @@ X86TargetInfo::validateAsmConstraint(const char *&Name, // x86_64 instructions. case 'N': // unsigned 8-bit integer constant for use with in and out // instructions. - info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister); + Info.setAllowsRegister(); return true; } } @@ -997,7 +997,7 @@ public: NumAliases = 0; } virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { + TargetInfo::ConstraintInfo &Info) const { // FIXME: Check if this is complete switch (*Name) { default: @@ -1005,7 +1005,7 @@ public: case 'h': // r8-r15 case 'w': // VFP Floating point register single precision case 'P': // VFP Floating point register double precision - info = (TargetInfo::ConstraintInfo)(info|TargetInfo::CI_AllowsRegister); + Info.setAllowsRegister(); return true; } return false; diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 9fd701419b..6fc4a08dd5 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -731,8 +731,7 @@ llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S, const Expr *InputExpr, std::string &ConstraintStr) { llvm::Value *Arg; - if ((Info & TargetInfo::CI_AllowsRegister) || - !(Info & TargetInfo::CI_AllowsMemory)) { + if (Info.allowsRegister() || !Info.allowsMemory()) { const llvm::Type *Ty = ConvertType(InputExpr->getType()); if (Ty->isSingleValueType()) { @@ -818,8 +817,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { // If the first output operand is not a memory dest, we'll // make it the return value. - if (i == 0 && !(Info & TargetInfo::CI_AllowsMemory) && - DestValueType->isSingleValueType()) { + if (i == 0 && !Info.allowsMemory() && DestValueType->isSingleValueType()) { ResultAddr = Dest.getAddress(); ResultType = DestValueType; Constraints += "=" + OutputConstraint; @@ -832,13 +830,13 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { Constraints += OutputConstraint; } - if (Info & TargetInfo::CI_ReadWrite) { + if (Info.isReadWrite()) { InOutConstraints += ','; const Expr *InputExpr = S.getOutputExpr(i); llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, InOutConstraints); - if (Info & TargetInfo::CI_AllowsRegister) + if (Info.allowsRegister()) InOutConstraints += llvm::utostr(i); else InOutConstraints += OutputConstraint; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 1ee8188ec2..62623f37e3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -925,8 +925,8 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, std::string OutputConstraint(Literal->getStrData(), Literal->getByteLength()); - TargetInfo::ConstraintInfo info; - if (!Context.Target.validateOutputConstraint(OutputConstraint.c_str(),info)) + TargetInfo::ConstraintInfo Info; + if (!Context.Target.validateOutputConstraint(OutputConstraint.c_str(),Info)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_output_constraint) << OutputConstraint); @@ -938,7 +938,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, << OutputExpr->getSubExpr()->getSourceRange()); } - OutputConstraintInfos.push_back(info); + OutputConstraintInfos.push_back(Info); } for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { @@ -950,12 +950,12 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, std::string InputConstraint(Literal->getStrData(), Literal->getByteLength()); - TargetInfo::ConstraintInfo info; + TargetInfo::ConstraintInfo Info; if (!Context.Target.validateInputConstraint(InputConstraint.c_str(), &Names[0], &Names[0] + NumOutputs, &OutputConstraintInfos[0], - info)) { + Info)) { return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_input_constraint) << InputConstraint); } @@ -963,15 +963,14 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, ParenExpr *InputExpr = cast(Exprs[i]); // Only allow void types for memory constraints. - if ((info & TargetInfo::CI_AllowsMemory) - && !(info & TargetInfo::CI_AllowsRegister)) { + if (Info.allowsMemory() && !Info.allowsRegister()) { if (CheckAsmLValue(InputExpr, *this)) return StmtError(Diag(InputExpr->getSubExpr()->getLocStart(), diag::err_asm_invalid_lvalue_in_input) - << InputConstraint << InputExpr->getSubExpr()->getSourceRange()); + << InputConstraint << InputExpr->getSubExpr()->getSourceRange()); } - if (info & TargetInfo::CI_AllowsRegister) { + if (Info.allowsRegister()) { if (InputExpr->getType()->isVoidType()) { return StmtError(Diag(InputExpr->getSubExpr()->getLocStart(), diag::err_asm_invalid_type_in_input)