Skip to content

Commit

Permalink
[Xtensa] Implement support for __attribute__((short__call)) and `__…
Browse files Browse the repository at this point in the history
…attribute__((near))`
  • Loading branch information
sstefan1 committed Mar 5, 2024
1 parent 2bace8a commit df27f60
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 10 deletions.
16 changes: 14 additions & 2 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ def TargetX86 : TargetArch<["x86"]>;
def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>;
def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>;
def TargetXtensa : TargetArch<["xtensa"]>;
def TargetWindows : TargetSpec {
let OSes = ["Win32"];
}
Expand Down Expand Up @@ -1725,11 +1726,22 @@ def MipsLongCall : InheritableAttr, TargetSpecificAttr<TargetAnyMips> {
def MipsShortCall : InheritableAttr, TargetSpecificAttr<TargetAnyMips> {
let Spellings = [GCC<"short_call">, GCC<"near">];
let Subjects = SubjectList<[Function]>;
let Documentation = [MipsShortCallStyleDocs];
let SimpleHandler = 1;
let Documentation = [ShortCallStyleDocs];
let ParseKind = "ShortCall";
let HasCustomParsing = 1;
let SemaHandler = 1;
}
def : MutualExclusions<[MipsLongCall, MipsShortCall]>;

def XtensaShortCall : InheritableAttr, TargetSpecificAttr<TargetXtensa> {
let Spellings = [GCC<"short_call">, GCC<"near">];
let Subjects = SubjectList<[Function]>;
let Documentation = [ShortCallStyleDocs];
let ParseKind = "ShortCall";
let HasCustomParsing = 1;
let SemaHandler = 1;
}

def M68kInterrupt : InheritableAttr, TargetSpecificAttr<TargetM68k> {
// NOTE: If you add any additional spellings, ARMInterrupt's, MipsInterrupt's
// MSP430Interrupt's and AnyX86Interrupt's spellings must match.
Expand Down
13 changes: 7 additions & 6 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -2296,18 +2296,19 @@ as ``-mlong-calls`` and ``-mno-long-calls``.
}];
}

def MipsShortCallStyleDocs : Documentation {
def ShortCallStyleDocs : Documentation {
let Category = DocCatFunction;
let Heading = "short_call, near";
let Content = [{
Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``,
``__attribute__((short__call))``, and ``__attribute__((near))`` attributes
on MIPS targets. These attributes may only be added to function declarations
and change the code generated by the compiler when directly calling
on MIPS and Xtensa targets. These attributes may only be added to function
declarations and change the code generated by the compiler when directly calling
the function. The ``short_call`` and ``near`` attributes are synonyms and
allow calls to the function to be made using the ``jal`` instruction, which
requires the function to be located in the same naturally aligned 256MB segment
as the caller. The ``long_call`` and ``far`` attributes are synonyms and
allow calls to the function to be made using the ``jal`` instruction for MIPS and
``calln`` instruction for Xtensa, which requires the function to be located
in the same naturally aligned 256MB segment as the caller.
The ``long_call`` and ``far`` attributes are synonyms and
require the use of a different call sequence that works regardless
of the distance between the functions.

Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CodeGen/Targets/Xtensa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,16 @@ class XtensaTargetCodeGenInfo : public TargetCodeGenInfo {
public:
XtensaTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
: TargetCodeGenInfo(std::make_unique<XtensaABIInfo>(CGT)) {}

void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
return;
llvm::Function *Fn = cast<llvm::Function>(GV);
if (FD->hasAttr<XtensaShortCallAttr>())
Fn->addFnAttr("short-call");
}
};
} // namespace

Expand Down
43 changes: 43 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7605,6 +7605,32 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
}

static void handleMipsShortCall(Sema &S, Decl *D, const ParsedAttr &AL) {
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'short_call'" << ExpectedFunction;
return;
}

if (!AL.checkExactlyNumArgs(S, 0))
return;

handleSimpleAttribute<MipsShortCallAttr>(S, D, AL);
}

static void handleXtensaShortCall(Sema &S, Decl *D, const ParsedAttr &AL){
if (!isFunctionOrMethod(D)) {
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
<< "'short_call'" << ExpectedFunction;
return;
}

if (!AL.checkExactlyNumArgs(S, 0))
return;

handleSimpleAttribute<XtensaShortCallAttr>(S, D, AL);
}

static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD) {
// Add preserve_access_index attribute to all fields and inner records.
for (auto *D : RD->decls()) {
Expand Down Expand Up @@ -7802,6 +7828,20 @@ static void handleRISCVInterruptAttr(Sema &S, Decl *D,
D->addAttr(::new (S.Context) RISCVInterruptAttr(S.Context, AL, Kind));
}

static void handleShortCallAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
switch (S.Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::xtensa:
handleXtensaShortCall(S, D, AL);
break;
case llvm::Triple::mips64:
case llvm::Triple::mips:
handleMipsShortCall(S, D, AL);
break;
default:
break;
}
}

static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Dispatch the interrupt attribute based on the current target.
switch (S.Context.getTargetInfo().getTriple().getArch()) {
Expand Down Expand Up @@ -9493,6 +9533,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_UsingIfExists:
handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL);
break;
case ParsedAttr::AT_ShortCall:
handleShortCallAttr(S, D, AL);
break;
}
}

Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeGen/Xtensa/xtensa-short-call.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %clang_cc1 -triple xtensa -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple xtensa -S -o - %s | FileCheck %s --check-prefix=ASM

void foo1 (void);
void __attribute__((short_call)) foo (void);
void __attribute__((near)) bar (void) { foo1(); foo(); }

// CHECK: define{{.*}} void @bar() [[NEAR:#[0-9]+]]

// CHECK: declare void @foo() [[SHORTDECL:#[0-9]+]]

// CHECK: attributes [[NEAR]] = { {{.*}} "short-call" {{.*}} }
// CHECK: attributes [[SHORTDECL]] = { {{.*}} "short-call" {{.*}} }

// ASM: callx8 a8
// ASM: call8 foo
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
// CHECK-NEXT: MinVectorWidth (SubjectMatchRule_function)
// CHECK-NEXT: Mips16 (SubjectMatchRule_function)
// CHECK-NEXT: MipsLongCall (SubjectMatchRule_function)
// CHECK-NEXT: MipsShortCall (SubjectMatchRule_function)
// CHECK-NEXT: ShortCall (SubjectMatchRule_function)
// CHECK-NEXT: NSConsumed (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: NSConsumesSelf (SubjectMatchRule_objc_method)
// CHECK-NEXT: NSErrorDomain (SubjectMatchRule_enum)
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,7 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,

std::string name;
unsigned char TF = 0;
bool HasShortCallAttr = false;

// Accept direct calls by converting symbolic call addresses to the
// associated Target* opcodes.
Expand All @@ -1414,9 +1415,12 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,

const GlobalValue *GV = G->getGlobal();
name = GV->getName().str();
if (auto *F = dyn_cast<Function>(GV))
if (F->hasFnAttribute("short-call"))
HasShortCallAttr = true;
}

if ((!name.empty()) && isLongCall(name.c_str())) {
if (!name.empty() && isLongCall(name.c_str()) && !HasShortCallAttr) {
// Create a constant pool entry for the callee address
XtensaCP::XtensaCPModifier Modifier = XtensaCP::no_modifier;

Expand Down

0 comments on commit df27f60

Please sign in to comment.