summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2011-04-14 20:06:49 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2011-04-14 20:06:49 +0000
commit231e875b5c44db3197d548b8b7c16d1bc3d8a81e (patch)
treee3e1f7f51788639d1223864f031d251d347c038d /clang/lib
parentfdc33cbecd636a9218c30aed114ac6cfce6464f0 (diff)
downloadbcm5719-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.cpp2
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp2
-rw-r--r--clang/lib/AST/Type.cpp2
-rw-r--r--clang/lib/AST/TypePrinter.cpp16
-rw-r--r--clang/lib/CodeGen/CGCall.cpp5
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp18
-rw-r--r--clang/lib/Sema/AttributeList.cpp1
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp51
-rw-r--r--clang/lib/Sema/SemaType.cpp5
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();
OpenPOWER on IntegriCloud