edward-jones created this revision.
Herald added subscribers: vkmr, frasercrmck, dexonsmith, dang, jdoerfert,
evandro, luismarques, apazos, sameer.abuasal, simoncook, s.egerton, Jim, benna,
psnobl, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, zzheng,
jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, johnrusso, rbar, asb.
Herald added a reviewer: aaron.ballman.
edward-jones requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.
This is the Clang component of a change to add support for a proposed 'overlay'
system for RISC-V to LLVM.
This adds two new attributes, __attribute__((overlaydata)), and
__attribute__((overlaycall)), which are used to mark functions or global data
as only accessible through the overlay engine. Internally they are converted to
'overlay-data' and 'overlay-call' attributes in LLVM IR.
This change also adds the option `-fcomrv` to enable use of the overlay system.
This has the effect of reserving registers x28, x29, x30 and x31 for exclusive
used by the overlay engine.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D109372
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/LangOptions.def
clang/include/clang/Driver/Options.td
clang/lib/AST/TypePrinter.cpp
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Driver/ToolChains/Arch/RISCV.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Driver/ToolChains/RISCVToolchain.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/CodeGen/riscv-overlaycall.c
clang/test/Driver/riscv-comrv.c
clang/test/Misc/pragma-attribute-supported-attributes-list.test
clang/test/Sema/attr-overlaycall.c
clang/test/Sema/riscv-overlaycall-namespace.cpp
Index: clang/test/Sema/riscv-overlaycall-namespace.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/riscv-overlaycall-namespace.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -verify -fsyntax-only -fcomrv
+// RUN: %clang_cc1 %s -triple riscv64-unknown-elf -verify -fsyntax-only -fcomrv
+
+namespace {
+class foo {
+public:
+ static int X() __attribute__((overlaycall)) { return 0; } // expected-error {{RISC-V 'overlaycall' attribute not supported on static functions}}
+};
+} // end of anonymous namespace
+
+namespace X {
+ class bar {
+ public:
+ static int X() __attribute__((overlaycall)) { return 1; }
+ };
+} // end of namespace X
+
+extern "C" {
+int main(void) { return foo::X() + X::bar::X(); }
+}
Index: clang/test/Sema/attr-overlaycall.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-overlaycall.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple riscv32 -fcomrv -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple riscv64 -fcomrv -fsyntax-only -verify %s
+
+int notAFunction __attribute__((overlaycall));
+// expected-warning@-1 {{'overlaycall' attribute only applies to functions}}
+
+void incompatForwardDecl(int x);
+void __attribute__((overlaycall)) incompatForwardDecl(int x) {}
+// expected-error@-1 {{redeclaration of 'incompatForwardDecl' must not have the RISC-V 'overlaycall' attribute}}
+// expected-note@-3 {{previous definition is here}}
+
+static void staticcall() __attribute__((overlaycall)) {}
+// expected-error@-1 {{attribute not supported on static functions}}
+// expected-warning@-2 {{GCC does not allow 'overlaycall' attribute in this position on a function definition}}
+
+static void __attribute__((overlaycall)) staticcall2(){}
+// expected-error@-1 {{attribute not supported on static functions}}
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -147,6 +147,7 @@
// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: PatchableFunctionEntry (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: Pointer (SubjectMatchRule_record_not_is_union)
+// CHECK-NEXT: RISCVOverlayCall (SubjectMatchRule_function)
// CHECK-NEXT: ReleaseHandle (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function)
// CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function)
Index: clang/test/Driver/riscv-comrv.c
===================================================================
--- /dev/null
+++ clang/test/Driver/riscv-comrv.c
@@ -0,0 +1,8 @@
+// Check ComRV Driver Arguments
+//
+// REQUIRES: riscv-registered-target
+//
+// RUN: %clang -target riscv32-unknown-elf -fcomrv \
+// RUN: -march=rv32if -mabi=ilp32f -### -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix=INVALID-ABI %s
+// INVALID-ABI: invalid ABI 'ilp32f' when using -fcomrv
Index: clang/test/CodeGen/riscv-overlaycall.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/riscv-overlaycall.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -triple=riscv64 -fcomrv -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+int __attribute__((overlaycall)) test_overlay_func(void) {
+// CHECK-LABEL: define{{.*}}@test_overlay_func() #0 align 4 {
+// CHECK: attributes #0 = {
+// CHECK-SAME: "overlay-call"
+ return 5;
+}
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -2039,6 +2039,28 @@
D->addAttr(::new (S.Context) CmseNSEntryAttr(S.Context, AL));
}
+static void handleRISCVOverlayCallAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!isFunctionOrMethod(D)) {
+ S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+ << AL << ExpectedFunctionOrMethod;
+ return;
+ }
+
+ const auto *FD = cast<FunctionDecl>(D);
+ if (!FD->isExternallyVisible()) {
+ S.Diag(AL.getLoc(), diag::err_overlaycall_static);
+ AL.setInvalid();
+ return;
+ }
+
+ // overlaycall implies noinline
+ Attr *A = ::new(S.Context) NoInlineAttr(S.Context, AL);
+ A->setImplicit(true);
+ D->addAttr(A);
+
+ handleSimpleAttribute<RISCVOverlayCallAttr>(S, D, AL);
+}
+
static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (AL.isDeclspecAttribute()) {
const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
@@ -8264,6 +8286,9 @@
case ParsedAttr::AT_CmseNSEntry:
handleCmseNSEntryAttr(S, D, AL);
break;
+ case ParsedAttr::AT_RISCVOverlayCall:
+ handleRISCVOverlayCallAttr(S, D, AL);
+ break;
case ParsedAttr::AT_StdCall:
case ParsedAttr::AT_CDecl:
case ParsedAttr::AT_FastCall:
@@ -8483,6 +8508,15 @@
handleArmBuiltinAliasAttr(S, D, AL);
break;
+ case ParsedAttr::AT_RISCVOverlayData:
+ if (!S.getLangOpts().RISCVOverlayFunctions) {
+ AL.setInvalid();
+ S.Diag(AL.getLoc(), diag::err_overlaydata_unsupported);
+ break;
+ }
+ D->addAttr(::new (S.Context) RISCVOverlayDataAttr(S.Context, AL));
+ break;
+
case ParsedAttr::AT_AcquireHandle:
handleAcquireHandleAttr(S, D, AL);
break;
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -3358,6 +3358,15 @@
}
}
+ bool NewIsOverlayCall = New->hasAttr<RISCVOverlayCallAttr>();
+ bool OldIsOverlayCall = Old->hasAttr<RISCVOverlayCallAttr>();
+ if (NewIsOverlayCall != OldIsOverlayCall) {
+ Diag(New->getLocation(), diag::err_overlaycall_mismatch)
+ << New << OldIsOverlayCall;
+ notePreviousDefinition(Old, New->getLocation());
+ return true;
+ }
+
if (const auto *ILA = New->getAttr<InternalLinkageAttr>())
if (!Old->hasAttr<InternalLinkageAttr>()) {
Diag(New->getLocation(), diag::err_attribute_missing_on_first_decl)
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -4063,6 +4063,9 @@
{std::string(Split.first), std::string(Split.second)});
}
+ // RISC-V overlay functions support
+ Opts.RISCVOverlayFunctions = Args.hasArg(OPT_fcomrv);
+
return Diags.getNumErrors() == NumErrorsBefore;
}
@@ -4455,6 +4458,9 @@
Res.getCodeGenOpts().Argv0 = Argv0;
Res.getCodeGenOpts().CommandLineArgs = CommandLineArgs;
+ // RISC-V overlay functions support
+ LangOpts.RISCVOverlayFunctions = Args.hasArg(OPT_fcomrv);
+
FixupInvocation(Res, Diags, Args, DashX);
return Diags.getNumErrors() == NumErrorsBefore;
Index: clang/lib/Driver/ToolChains/RISCVToolchain.cpp
===================================================================
--- clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "RISCVToolchain.h"
+#include "Arch/RISCV.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/InputInfo.h"
Index: clang/lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -12,6 +12,7 @@
#include "Arch/M68k.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
#include "Arch/SystemZ.h"
#include "Arch/VE.h"
#include "Arch/X86.h"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2095,6 +2095,16 @@
CmdArgs.push_back("-tune-cpu");
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
}
+
+ // If comrv mode is requested, pass on this flag, and produce an error if an
+ // invalid ABI has been requested
+ if (Args.getLastArg(options::OPT_fcomrv)) {
+ CmdArgs.push_back("-fcomrv");
+
+ if (ABIName != "ilp32")
+ getToolChain().getDriver().Diag(diag::err_drv_invalid_riscv_abi_fcomrv)
+ << ABIName;
+ }
}
void Clang::AddSparcTargetArgs(const ArgList &Args,
Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -492,6 +492,15 @@
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
getRISCFeaturesFromMcpu(D, Triple, Args, A, A->getValue(), Features);
+ // Handle features corresponding to custom language feature
+ // "RISCVOverlayFunctions"
+ if (Args.hasArg(options::OPT_fcomrv)) {
+ Features.push_back("+reserve-x28"); // Overlay Stack Register
+ Features.push_back("+reserve-x29"); // Overlay Stack Frames Pool Register
+ Features.push_back("+reserve-x30"); // Overlay Address Token Reg
+ Features.push_back("+reserve-x31"); // Overlay Entry Point Address Register
+ }
+
// Handle features corresponding to "-ffixed-X" options
if (Args.hasArg(options::OPT_ffixed_x1))
Features.push_back("+reserve-x1");
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1880,6 +1880,10 @@
if (LangOpts.FunctionAlignment)
F->setAlignment(llvm::Align(1ull << LangOpts.FunctionAlignment));
+ // Overlay functions must have a minimum 4-byte alignment.
+ if (F->getAlignment() < 4 && D->hasAttr<RISCVOverlayCallAttr>())
+ F->setAlignment(llvm::Align(4));
+
// Some C++ ABIs require 2-byte alignment for member functions, in order to
// reserve a bit for differentiating between virtual and non-virtual member
// functions. If the current target's C++ ABI requires this and this is a
@@ -4525,6 +4529,9 @@
if (CGDebugInfo *DI = getModuleDebugInfo())
if (getCodeGenOpts().hasReducedDebugInfo())
DI->EmitGlobalVariable(GV, D);
+
+ if (D->hasAttr<RISCVOverlayDataAttr>())
+ GV->addAttribute("overlay-data");
}
void CodeGenModule::EmitExternalVarDeclaration(const VarDecl *D) {
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -2042,6 +2042,8 @@
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
if (TargetDecl->hasAttr<ConvergentAttr>())
FuncAttrs.addAttribute(llvm::Attribute::Convergent);
+ if (TargetDecl->hasAttr<RISCVOverlayCallAttr>())
+ FuncAttrs.addAttribute("overlay-call");
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
AddAttributesFromFunctionProtoType(
Index: clang/lib/AST/TypePrinter.cpp
===================================================================
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1743,6 +1743,9 @@
case attr::ArmMveStrictPolymorphism:
OS << "__clang_arm_mve_strict_polymorphism";
break;
+ case attr::RISCVOverlayData:
+ OS << "overlaydata";
+ break;
}
OS << "))";
}
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3229,6 +3229,9 @@
HelpText<"Equivalent to -mcmodel=medium, compatible with RISC-V gcc.">;
def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_Group>,
HelpText<"Enable use of experimental RISC-V extensions.">;
+def fcomrv : Flag<["-"], "fcomrv">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Enable RISC-V overlay functions support">;
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -428,6 +428,8 @@
"Controls how scalar integer arguments are extended in calls "
"to unprototyped and varargs functions")
+LANGOPT(RISCVOverlayFunctions, 1, 0, "RISC-V overlay functions support")
+
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -309,6 +309,16 @@
"repeated RISC-V 'interrupt' attribute">, InGroup<IgnoredAttributes>;
def note_riscv_repeated_interrupt_attribute : Note<
"repeated RISC-V 'interrupt' attribute is here">;
+def err_overlaycall_unsupported : Error<
+ "RISC-V 'overlaycall' attribute requires support to be enabled with "
+ "the -fcomrv option">;
+def err_overlaycall_static : Error<
+ "RISC-V 'overlaycall' attribute not supported on static functions">;
+def err_overlaycall_mismatch : Error<
+ "redeclaration of %0 must %select{not |}1have the RISC-V 'overlaycall' attribute">;
+def err_overlaydata_unsupported : Error<
+ "RISC-V 'overlaydata' attribute requires support to be enabled with "
+ "the -fcomrv option">;
def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
def warn_unused_but_set_parameter : Warning<"parameter %0 set but not used">,
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -32,6 +32,8 @@
def warn_drv_invalid_arch_name_with_suggestion : Warning<
"ignoring invalid /arch: argument '%0'; for %select{64|32}1-bit expected one of %2">,
InGroup<UnusedCommandLineArgument>;
+def err_drv_invalid_riscv_abi_fcomrv : Error<
+ "invalid ABI '%0' when using -fcomrv">;
def warn_drv_avr_mcu_not_specified : Warning<
"no target microcontroller specified on command line, cannot "
"link standard libraries, please pass -mmcu=<mcu name>">,
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -2142,6 +2142,20 @@
}];
}
+def RISCVOverlayDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "overlaycall, overlaydata (RISCV)";
+ let Content = [{
+``__attribute__((overlaycall))`` indicates that a function resides in an
+overlay and therefore any calls to or from that function must be handled
+through the overlay engine.
+
+``__attribute__((overlaydata))`` is used to mark global constants and signifies
+that the global is in an overlay and can only be accessed using the overlay
+engine.
+ }];
+}
+
def AVRInterruptDocs : Documentation {
let Category = DocCatFunction;
let Heading = "interrupt (AVR)";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -118,6 +118,11 @@
def GlobalVar : SubsetSubject<Var,
[{S->hasGlobalStorage()}], "global variables">;
+def GlobalConst : SubsetSubject<Var,
+ [{S->hasGlobalStorage() &&
+ S->getType().isConstQualified()}],
+ "global constants">;
+
def InlineFunction : SubsetSubject<Function,
[{S->isInlineSpecified()}], "inline functions">;
@@ -339,6 +344,9 @@
// Language option for CMSE extensions
def Cmse : LangOpt<"Cmse">;
+// Language option for Overlay functions
+def RISCVOverlayFunctions : LangOpt<"RISCVOverlayFunctions">;
+
// Defines targets for target-specific attributes. Empty lists are unchecked.
class TargetSpec {
// Specifies Architectures for which the target applies, based off the
@@ -1782,6 +1790,22 @@
let Documentation = [RISCVInterruptDocs];
}
+// This is not marked as a TargetSpecificAttr because that would trigger
+// an 'attribute ignored' warning, but we want to check it explicitly and
+// trigger an error.
+def RISCVOverlayCall : InheritableAttr {
+ let Spellings = [GCC<"overlaycall">];
+ let Subjects = SubjectList<[Function]>;
+ let LangOpts = [RISCVOverlayFunctions];
+ let Documentation = [RISCVOverlayDocs];
+}
+
+def RISCVOverlayData : TypeAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [GCC<"overlaydata">];
+ let Subjects = SubjectList<[GlobalConst]>;
+ let Documentation = [RISCVOverlayDocs];
+}
+
// This is not a TargetSpecificAttr so that is silently accepted and
// ignored on other targets as encouraged by the OpenCL spec.
//
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits