Skip to content

Commit 1a116db

Browse files
committedJul 20, 2017
[CodeGen][mips] Support long_call/far/near attributes
This patch adds support for the `long_call`, `far`, and `near` attributes for MIPS targets. The `long_call` and `far` attributes are synonyms. All these attributes override `-mlong-calls` / `-mno-long-calls` command line options for particular function. Differential revision: https://reviews.llvm.org/D35479 llvm-svn: 308667
1 parent 39aa5db commit 1a116db

File tree

10 files changed

+176
-45
lines changed

10 files changed

+176
-45
lines changed
 

Diff for: ‎clang/include/clang/Basic/Attr.td

+12
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,18 @@ def MicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> {
11881188
let Documentation = [MicroMipsDocs];
11891189
}
11901190

1191+
def MipsLongCall : InheritableAttr, TargetSpecificAttr<TargetMips> {
1192+
let Spellings = [GCC<"long_call">, GCC<"far">];
1193+
let Subjects = SubjectList<[Function]>;
1194+
let Documentation = [MipsCallStyleDocs];
1195+
}
1196+
1197+
def MipsShortCall : InheritableAttr, TargetSpecificAttr<TargetMips> {
1198+
let Spellings = [GCC<"near">];
1199+
let Subjects = SubjectList<[Function]>;
1200+
let Documentation = [MipsCallStyleDocs];
1201+
}
1202+
11911203
def Mode : Attr {
11921204
let Spellings = [GCC<"mode">];
11931205
let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag,

Diff for: ‎clang/include/clang/Basic/AttrDocs.td

+20
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,26 @@ on the command line.
13231323
}];
13241324
}
13251325

1326+
def MipsCallStyleDocs : Documentation {
1327+
let Category = DocCatFunction;
1328+
let Content = [{
1329+
Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
1330+
and ``__attribute__((near))`` attributes on MIPS targets. These attributes may
1331+
only be added to function declarations and change the code generated
1332+
by the compiler when directly calling the function. The ``near`` attribute
1333+
allows calls to the function to be made using the ``jal`` instruction, which
1334+
requires the function to be located in the same naturally aligned 256MB
1335+
segment as the caller. The ``long_call`` and ``far`` attributes are synonyms
1336+
and require the use of a different call sequence that works regardless
1337+
of the distance between the functions.
1338+
1339+
These attributes have no effect for position-independent code.
1340+
1341+
These attributes take priority over command line switches such
1342+
as ``-mlong-calls`` and ``-mno-long-calls``.
1343+
}];
1344+
}
1345+
13261346
def AVRInterruptDocs : Documentation {
13271347
let Category = DocCatFunction;
13281348
let Content = [{

Diff for: ‎clang/lib/CodeGen/CodeGenModule.cpp

+12-4
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,7 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
10801080
GO->setSection(SA->getName());
10811081
}
10821082

1083-
getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
1083+
getTargetCodeGenInfo().setTargetAttributes(D, GO, *this, ForDefinition);
10841084
}
10851085

10861086
void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
@@ -1147,7 +1147,9 @@ void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
11471147

11481148
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
11491149
bool IsIncompleteFunction,
1150-
bool IsThunk) {
1150+
bool IsThunk,
1151+
ForDefinition_t IsForDefinition) {
1152+
11511153
if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) {
11521154
// If this is an intrinsic function, set the function's attributes
11531155
// to the intrinsic's attributes.
@@ -1157,8 +1159,13 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
11571159

11581160
const auto *FD = cast<FunctionDecl>(GD.getDecl());
11591161

1160-
if (!IsIncompleteFunction)
1162+
if (!IsIncompleteFunction) {
11611163
SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);
1164+
// Setup target-specific attributes.
1165+
if (!IsForDefinition)
1166+
getTargetCodeGenInfo().setTargetAttributes(FD, F, *this,
1167+
NotForDefinition);
1168+
}
11621169

11631170
// Add the Returned attribute for "this", except for iOS 5 and earlier
11641171
// where substantial code, including the libstdc++ dylib, was compiled with
@@ -2123,7 +2130,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
21232130

21242131
assert(F->getName() == MangledName && "name was uniqued!");
21252132
if (D)
2126-
SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk);
2133+
SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk,
2134+
IsForDefinition);
21272135
if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) {
21282136
llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex);
21292137
F->addAttributes(llvm::AttributeList::FunctionIndex, B);

Diff for: ‎clang/lib/CodeGen/CodeGenModule.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,8 @@ class CodeGenModule : public CodeGenTypeCache {
12391239

12401240
/// Set function attributes for a function declaration.
12411241
void SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
1242-
bool IsIncompleteFunction, bool IsThunk);
1242+
bool IsIncompleteFunction, bool IsThunk,
1243+
ForDefinition_t IsForDefinition);
12431244

12441245
void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr);
12451246

Diff for: ‎clang/lib/CodeGen/TargetInfo.cpp

+81-37
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,8 @@ class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
10371037
const llvm::Triple &Triple, const CodeGenOptions &Opts);
10381038

10391039
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
1040-
CodeGen::CodeGenModule &CGM) const override;
1040+
CodeGen::CodeGenModule &CGM,
1041+
ForDefinition_t IsForDefinition) const override;
10411042

10421043
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
10431044
// Darwin uses different dwarf register numbers for EH.
@@ -1904,9 +1905,11 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
19041905
}
19051906
}
19061907

1907-
void X86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
1908-
llvm::GlobalValue *GV,
1909-
CodeGen::CodeGenModule &CGM) const {
1908+
void X86_32TargetCodeGenInfo::setTargetAttributes(
1909+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
1910+
ForDefinition_t IsForDefinition) const {
1911+
if (!IsForDefinition)
1912+
return;
19101913
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
19111914
if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
19121915
// Get the LLVM function.
@@ -2266,7 +2269,10 @@ class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
22662269
}
22672270

22682271
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
2269-
CodeGen::CodeGenModule &CGM) const override {
2272+
CodeGen::CodeGenModule &CGM,
2273+
ForDefinition_t IsForDefinition) const override {
2274+
if (!IsForDefinition)
2275+
return;
22702276
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
22712277
if (FD->hasAttr<AnyX86InterruptAttr>()) {
22722278
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -2314,7 +2320,8 @@ class WinX86_32TargetCodeGenInfo : public X86_32TargetCodeGenInfo {
23142320
Win32StructABI, NumRegisterParameters, false) {}
23152321

23162322
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
2317-
CodeGen::CodeGenModule &CGM) const override;
2323+
CodeGen::CodeGenModule &CGM,
2324+
ForDefinition_t IsForDefinition) const override;
23182325

23192326
void getDependentLibraryOption(llvm::StringRef Lib,
23202327
llvm::SmallString<24> &Opt) const override {
@@ -2342,11 +2349,12 @@ static void addStackProbeSizeTargetAttribute(const Decl *D,
23422349
}
23432350
}
23442351

2345-
void WinX86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
2346-
llvm::GlobalValue *GV,
2347-
CodeGen::CodeGenModule &CGM) const {
2348-
X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
2349-
2352+
void WinX86_32TargetCodeGenInfo::setTargetAttributes(
2353+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
2354+
ForDefinition_t IsForDefinition) const {
2355+
X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM, IsForDefinition);
2356+
if (!IsForDefinition)
2357+
return;
23502358
addStackProbeSizeTargetAttribute(D, GV, CGM);
23512359
}
23522360

@@ -2357,7 +2365,8 @@ class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
23572365
: TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
23582366

23592367
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
2360-
CodeGen::CodeGenModule &CGM) const override;
2368+
CodeGen::CodeGenModule &CGM,
2369+
ForDefinition_t IsForDefinition) const override;
23612370

23622371
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
23632372
return 7;
@@ -2386,11 +2395,12 @@ class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
23862395
}
23872396
};
23882397

2389-
void WinX86_64TargetCodeGenInfo::setTargetAttributes(const Decl *D,
2390-
llvm::GlobalValue *GV,
2391-
CodeGen::CodeGenModule &CGM) const {
2392-
TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
2393-
2398+
void WinX86_64TargetCodeGenInfo::setTargetAttributes(
2399+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
2400+
ForDefinition_t IsForDefinition) const {
2401+
TargetCodeGenInfo::setTargetAttributes(D, GV, CGM, IsForDefinition);
2402+
if (!IsForDefinition)
2403+
return;
23942404
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
23952405
if (FD->hasAttr<AnyX86InterruptAttr>()) {
23962406
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -5475,7 +5485,10 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
54755485
}
54765486

54775487
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
5478-
CodeGen::CodeGenModule &CGM) const override {
5488+
CodeGen::CodeGenModule &CGM,
5489+
ForDefinition_t IsForDefinition) const override {
5490+
if (!IsForDefinition)
5491+
return;
54795492
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
54805493
if (!FD)
54815494
return;
@@ -5517,7 +5530,8 @@ class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo {
55175530
: ARMTargetCodeGenInfo(CGT, K) {}
55185531

55195532
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
5520-
CodeGen::CodeGenModule &CGM) const override;
5533+
CodeGen::CodeGenModule &CGM,
5534+
ForDefinition_t IsForDefinition) const override;
55215535

55225536
void getDependentLibraryOption(llvm::StringRef Lib,
55235537
llvm::SmallString<24> &Opt) const override {
@@ -5531,8 +5545,11 @@ class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo {
55315545
};
55325546

55335547
void WindowsARMTargetCodeGenInfo::setTargetAttributes(
5534-
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
5535-
ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
5548+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM,
5549+
ForDefinition_t IsForDefinition) const {
5550+
ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM, IsForDefinition);
5551+
if (!IsForDefinition)
5552+
return;
55365553
addStackProbeSizeTargetAttribute(D, GV, CGM);
55375554
}
55385555
}
@@ -6061,7 +6078,9 @@ class NVPTXTargetCodeGenInfo : public TargetCodeGenInfo {
60616078
: TargetCodeGenInfo(new NVPTXABIInfo(CGT)) {}
60626079

60636080
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
6064-
CodeGen::CodeGenModule &M) const override;
6081+
CodeGen::CodeGenModule &M,
6082+
ForDefinition_t IsForDefinition) const override;
6083+
60656084
private:
60666085
// Adds a NamedMDNode with F, Name, and Operand as operands, and adds the
60676086
// resulting MDNode to the nvvm.annotations MDNode.
@@ -6115,9 +6134,11 @@ Address NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
61156134
llvm_unreachable("NVPTX does not support varargs");
61166135
}
61176136

6118-
void NVPTXTargetCodeGenInfo::
6119-
setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
6120-
CodeGen::CodeGenModule &M) const{
6137+
void NVPTXTargetCodeGenInfo::setTargetAttributes(
6138+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
6139+
ForDefinition_t IsForDefinition) const {
6140+
if (!IsForDefinition)
6141+
return;
61216142
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
61226143
if (!FD) return;
61236144

@@ -6553,14 +6574,17 @@ class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
65536574
MSP430TargetCodeGenInfo(CodeGenTypes &CGT)
65546575
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
65556576
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
6556-
CodeGen::CodeGenModule &M) const override;
6577+
CodeGen::CodeGenModule &M,
6578+
ForDefinition_t IsForDefinition) const override;
65576579
};
65586580

65596581
}
65606582

6561-
void MSP430TargetCodeGenInfo::setTargetAttributes(const Decl *D,
6562-
llvm::GlobalValue *GV,
6563-
CodeGen::CodeGenModule &M) const {
6583+
void MSP430TargetCodeGenInfo::setTargetAttributes(
6584+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
6585+
ForDefinition_t IsForDefinition) const {
6586+
if (!IsForDefinition)
6587+
return;
65646588
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
65656589
if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
65666590
// Handle 'interrupt' attribute:
@@ -6619,10 +6643,21 @@ class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
66196643
}
66206644

66216645
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
6622-
CodeGen::CodeGenModule &CGM) const override {
6646+
CodeGen::CodeGenModule &CGM,
6647+
ForDefinition_t IsForDefinition) const override {
66236648
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
66246649
if (!FD) return;
66256650
llvm::Function *Fn = cast<llvm::Function>(GV);
6651+
6652+
if (FD->hasAttr<MipsLongCallAttr>())
6653+
Fn->addFnAttr("long-call");
6654+
else if (FD->hasAttr<MipsShortCallAttr>())
6655+
Fn->addFnAttr("short-call");
6656+
6657+
// Other attributes do not have a meaning for declarations.
6658+
if (!IsForDefinition)
6659+
return;
6660+
66266661
if (FD->hasAttr<Mips16Attr>()) {
66276662
Fn->addFnAttr("mips16");
66286663
}
@@ -6992,7 +7027,10 @@ class AVRTargetCodeGenInfo : public TargetCodeGenInfo {
69927027
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) { }
69937028

69947029
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
6995-
CodeGen::CodeGenModule &CGM) const override {
7030+
CodeGen::CodeGenModule &CGM,
7031+
ForDefinition_t IsForDefinition) const override {
7032+
if (!IsForDefinition)
7033+
return;
69967034
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
69977035
if (!FD) return;
69987036
auto *Fn = cast<llvm::Function>(GV);
@@ -7020,11 +7058,15 @@ class TCETargetCodeGenInfo : public DefaultTargetCodeGenInfo {
70207058
: DefaultTargetCodeGenInfo(CGT) {}
70217059

70227060
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
7023-
CodeGen::CodeGenModule &M) const override;
7061+
CodeGen::CodeGenModule &M,
7062+
ForDefinition_t IsForDefinition) const override;
70247063
};
70257064

70267065
void TCETargetCodeGenInfo::setTargetAttributes(
7027-
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
7066+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
7067+
ForDefinition_t IsForDefinition) const {
7068+
if (!IsForDefinition)
7069+
return;
70287070
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
70297071
if (!FD) return;
70307072

@@ -7364,7 +7406,8 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
73647406
AMDGPUTargetCodeGenInfo(CodeGenTypes &CGT)
73657407
: TargetCodeGenInfo(new AMDGPUABIInfo(CGT)) {}
73667408
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
7367-
CodeGen::CodeGenModule &M) const override;
7409+
CodeGen::CodeGenModule &M,
7410+
ForDefinition_t IsForDefinition) const override;
73687411
unsigned getOpenCLKernelCallingConv() const override;
73697412

73707413
llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
@@ -7380,9 +7423,10 @@ class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
73807423
}
73817424

73827425
void AMDGPUTargetCodeGenInfo::setTargetAttributes(
7383-
const Decl *D,
7384-
llvm::GlobalValue *GV,
7385-
CodeGen::CodeGenModule &M) const {
7426+
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M,
7427+
ForDefinition_t IsForDefinition) const {
7428+
if (!IsForDefinition)
7429+
return;
73867430
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
73877431
if (!FD)
73887432
return;

Diff for: ‎clang/lib/CodeGen/TargetInfo.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
1616
#define LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
1717

18+
#include "CodeGenModule.h"
1819
#include "CGValue.h"
1920
#include "clang/AST/Type.h"
2021
#include "clang/Basic/LLVM.h"
@@ -34,7 +35,6 @@ class Decl;
3435
namespace CodeGen {
3536
class ABIInfo;
3637
class CallArgList;
37-
class CodeGenModule;
3838
class CodeGenFunction;
3939
class CGFunctionInfo;
4040

@@ -55,7 +55,8 @@ class TargetCodeGenInfo {
5555
/// setTargetAttributes - Provides a convenient hook to handle extra
5656
/// target-specific attributes for the given global.
5757
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
58-
CodeGen::CodeGenModule &M) const {}
58+
CodeGen::CodeGenModule &M,
59+
ForDefinition_t IsForDefinition) const {}
5960

6061
/// emitTargetMD - Provides a convenient hook to handle extra
6162
/// target-specific metadata for the given global.

Diff for: ‎clang/lib/Sema/SemaDeclAttr.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -5986,6 +5986,14 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
59865986
case AttributeList::AT_NoMicroMips:
59875987
handleSimpleAttribute<NoMicroMipsAttr>(S, D, Attr);
59885988
break;
5989+
case AttributeList::AT_MipsLongCall:
5990+
handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>(
5991+
S, D, Attr);
5992+
break;
5993+
case AttributeList::AT_MipsShortCall:
5994+
handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>(
5995+
S, D, Attr);
5996+
break;
59895997
case AttributeList::AT_AMDGPUFlatWorkGroupSize:
59905998
handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr);
59915999
break;

Diff for: ‎clang/test/CodeGen/long-call-attr.c

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -triple mips-linux-gnu -emit-llvm -o - %s | FileCheck %s
2+
3+
void __attribute__((long_call)) foo1 (void);
4+
5+
void __attribute__((far)) foo2 (void) {}
6+
7+
// CHECK: define void @foo2() [[FAR:#[0-9]+]]
8+
9+
void __attribute__((near)) foo3 (void) { foo1(); }
10+
11+
// CHECK: define void @foo3() [[NEAR:#[0-9]+]]
12+
13+
// CHECK: declare void @foo1() [[LONGDECL:#[0-9]+]]
14+
15+
// CHECK: attributes [[FAR]] = { {{.*}} "long-call" {{.*}} }
16+
// CHECK: attributes [[NEAR]] = { {{.*}} "short-call" {{.*}} }
17+
// CHECK: attributes [[LONGDECL]] = { {{.*}} "long-call" {{.*}} }

Diff for: ‎clang/test/Misc/pragma-attribute-supported-attributes-list.test

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
// The number of supported attributes should never go down!
44

5-
// CHECK: #pragma clang attribute supports 62 attributes:
5+
// CHECK: #pragma clang attribute supports 64 attributes:
66
// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
77
// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
88
// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
@@ -31,6 +31,8 @@
3131
// CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
3232
// CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record)
3333
// CHECK-NEXT: MicroMips (SubjectMatchRule_function)
34+
// CHECK-NEXT: MipsLongCall (SubjectMatchRule_function)
35+
// CHECK-NEXT: MipsShortCall (SubjectMatchRule_function)
3436
// CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter)
3537
// CHECK-NEXT: NoDuplicate (SubjectMatchRule_function)
3638
// CHECK-NEXT: NoMicroMips (SubjectMatchRule_function)

Diff for: ‎clang/test/Sema/attr-long-call.c

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %clang_cc1 -triple mips-linux-gnu -fsyntax-only -verify %s
2+
3+
__attribute__((long_call(0))) void foo1(); // expected-error {{'long_call' attribute takes no arguments}}
4+
__attribute__((far(0))) void foo2(); // expected-error {{'far' attribute takes no arguments}}
5+
__attribute__((near(0))) void foo3(); // expected-error {{'near' attribute takes no arguments}}
6+
7+
__attribute((long_call)) int a; // expected-warning {{attribute only applies to functions}}
8+
__attribute((far)) int a; // expected-warning {{attribute only applies to functions}}
9+
__attribute((near)) int a; // expected-warning {{attribute only applies to functions}}
10+
11+
__attribute((long_call)) void foo4();
12+
__attribute((far)) void foo5();
13+
__attribute((near)) void foo6();
14+
15+
__attribute((long_call, far)) void foo7();
16+
17+
__attribute((far, near)) void foo8(); // expected-error {{'far' and 'near' attributes are not compatible}} \
18+
// expected-note {{conflicting attribute is here}}

0 commit comments

Comments
 (0)
Please sign in to comment.