diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2011-04-14 20:06:49 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2011-04-14 20:06:49 +0000 |
commit | 231e875b5c44db3197d548b8b7c16d1bc3d8a81e (patch) | |
tree | e3e1f7f51788639d1223864f031d251d347c038d /clang/lib | |
parent | fdc33cbecd636a9218c30aed114ac6cfce6464f0 (diff) | |
download | bcm5719-llvm-231e875b5c44db3197d548b8b7c16d1bc3d8a81e.tar.gz bcm5719-llvm-231e875b5c44db3197d548b8b7c16d1bc3d8a81e.zip |
Implement ARM pcs attribute. Basically it's another way of calling convention selection (AAPCS or
AAPCS+VFP), similar to fastcall / stdcall / whatevercall seen on x86.
In particular, all library functions should always be AAPCS regardless of floating point ABI used.
llvm-svn: 129534
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DumpXML.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 16 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/AttributeList.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 5 |
9 files changed, 93 insertions, 9 deletions
diff --git a/clang/lib/AST/DumpXML.cpp b/clang/lib/AST/DumpXML.cpp index 93ae1e37c9c..8355b2d901c 100644 --- a/clang/lib/AST/DumpXML.cpp +++ b/clang/lib/AST/DumpXML.cpp @@ -911,6 +911,8 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, case CC_X86StdCall: return set("cc", "x86_stdcall"); case CC_X86ThisCall: return set("cc", "x86_thiscall"); case CC_X86Pascal: return set("cc", "x86_pascal"); + case CC_AAPCS: return set("cc", "aapcs"); + case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); } } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 5b4dc5a1913..445d975625b 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -874,6 +874,8 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T, if (CC == CC_Default) CC = IsInstMethod ? getASTContext().getDefaultMethodCallConv() : CC_C; switch (CC) { + default: + assert(0 && "Unsupported CC for mangling"); case CC_Default: case CC_C: Out << 'A'; break; case CC_X86Pascal: Out << 'C'; break; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index b0726e42756..62e17f04488 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1169,6 +1169,8 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_X86FastCall: return "fastcall"; case CC_X86ThisCall: return "thiscall"; case CC_X86Pascal: return "pascal"; + case CC_AAPCS: return "aapcs"; + case CC_AAPCS_VFP: return "aapcs-vfp"; } llvm_unreachable("Invalid calling convention."); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index e287c46fa97..79fbcaa434e 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -400,6 +400,12 @@ void TypePrinter::printFunctionProto(const FunctionProtoType *T, case CC_X86Pascal: S += " __attribute__((pascal))"; break; + case CC_AAPCS: + S += " __attribute__((pcs(\"aapcs\")))"; + break; + case CC_AAPCS_VFP: + S += " __attribute__((pcs(\"aapcs-vfp\")))"; + break; } if (Info.getNoReturn()) S += " __attribute__((noreturn))"; @@ -851,6 +857,16 @@ void TypePrinter::printAttributed(const AttributedType *T, case AttributedType::attr_stdcall: S += "stdcall"; break; case AttributedType::attr_thiscall: S += "thiscall"; break; case AttributedType::attr_pascal: S += "pascal"; break; + case AttributedType::attr_pcs: { + S += "pcs("; + QualType t = T->getEquivalentType(); + while (!t->isFunctionType()) + t = t->getPointeeType(); + S += (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ? + "\"aapcs\"" : "\"aapcs-vfp\""); + S += ")"; + break; + } } S += "))"; } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0ba6789367f..dfe9049add1 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -36,6 +36,8 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; + case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS; + case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP; // TODO: add support for CC_X86Pascal to llvm } } @@ -104,6 +106,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D) { if (D->hasAttr<PascalAttr>()) return CC_X86Pascal; + if (PcsAttr *PCS = D->getAttr<PcsAttr>()) + return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP); + return CC_C; } diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 5db9a8e640b..cab60ee5b58 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2271,27 +2271,33 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { it != ie; ++it) it->info = classifyArgumentType(it->type); - const llvm::Triple &Triple(getContext().Target.getTriple()); + // Always honor user-specified calling convention. + if (FI.getCallingConvention() != llvm::CallingConv::C) + return; + + // Calling convention as default by an ABI. llvm::CallingConv::ID DefaultCC; - if (Triple.getEnvironmentName() == "gnueabi" || - Triple.getEnvironmentName() == "eabi") + llvm::StringRef Env = getContext().Target.getTriple().getEnvironmentName(); + if (Env == "gnueabi" || Env == "eabi") DefaultCC = llvm::CallingConv::ARM_AAPCS; else DefaultCC = llvm::CallingConv::ARM_APCS; + // If user did not ask for specific calling convention explicitly (e.g. via + // pcs attribute), set effective calling convention if it's different than ABI + // default. switch (getABIKind()) { case APCS: if (DefaultCC != llvm::CallingConv::ARM_APCS) FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_APCS); break; - case AAPCS: if (DefaultCC != llvm::CallingConv::ARM_AAPCS) FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS); break; - case AAPCS_VFP: - FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS_VFP); + if (DefaultCC != llvm::CallingConv::ARM_AAPCS_VFP) + FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS_VFP); break; } } diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index 792ab4ee8be..983c0e0c289 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -201,5 +201,6 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("nocommon", AT_nocommon) .Case("opencl_kernel_function", AT_opencl_kernel_function) .Case("uuid", AT_uuid) + .Case("pcs", AT_pcs) .Default(UnknownAttribute); } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 6d1a4c86f28..4c72c8390c5 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2427,6 +2427,30 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { case AttributeList::AT_pascal: d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context)); return; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return; + } + + llvm::StringRef StrRef = Str->getString(); + PcsAttr::PCSType PCS; + if (StrRef == "aapcs") + PCS = PcsAttr::AAPCS; + else if (StrRef == "aapcs-vfp") + PCS = PcsAttr::AAPCS_VFP; + else { + S.Diag(attr.getLoc(), diag::err_invalid_pcs); + attr.setInvalid(); + return; + } + + d->addAttr(::new (S.Context) PcsAttr(attr.getLoc(), S.Context, PCS)); + } default: llvm_unreachable("unexpected attribute kind"); return; @@ -2442,19 +2466,41 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { if (attr.isInvalid()) return true; - if (attr.getNumArgs() != 0) { + if (attr.getNumArgs() != 0 && + !(attr.getKind() == AttributeList::AT_pcs && attr.getNumArgs() == 1)) { Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; attr.setInvalid(); return true; } - // TODO: diagnose uses of these conventions on the wrong target. + // TODO: diagnose uses of these conventions on the wrong target. Or, better + // move to TargetAttributesSema one day. switch (attr.getKind()) { case AttributeList::AT_cdecl: CC = CC_C; break; case AttributeList::AT_fastcall: CC = CC_X86FastCall; break; case AttributeList::AT_stdcall: CC = CC_X86StdCall; break; case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break; case AttributeList::AT_pascal: CC = CC_X86Pascal; break; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return true; + } + + llvm::StringRef StrRef = Str->getString(); + if (StrRef == "aapcs") { + CC = CC_AAPCS; + break; + } else if (StrRef == "aapcs-vfp") { + CC = CC_AAPCS_VFP; + break; + } + // FALLS THROUGH + } default: llvm_unreachable("unexpected attribute kind"); return true; } @@ -2882,6 +2928,7 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, case AttributeList::AT_fastcall: case AttributeList::AT_thiscall: case AttributeList::AT_pascal: + case AttributeList::AT_pcs: HandleCallConvAttr(D, Attr, S); break; case AttributeList::AT_opencl_kernel_function: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 9c70d250ddc..d3408fc6acd 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -119,7 +119,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_stdcall: \ case AttributeList::AT_thiscall: \ case AttributeList::AT_pascal: \ - case AttributeList::AT_regparm + case AttributeList::AT_regparm: \ + case AttributeList::AT_pcs \ namespace { /// An object which stores processing state for the entire @@ -2244,6 +2245,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_thiscall; case AttributedType::attr_pascal: return AttributeList::AT_pascal; + case AttributedType::attr_pcs: + return AttributeList::AT_pcs; } llvm_unreachable("unexpected attribute kind!"); return AttributeList::Kind(); |