From 1fdfce5b6e3661fdc5e2bc27f3caac80b12d3830 Mon Sep 17 00:00:00 2001 From: Kristina Bessonova Date: Thu, 17 Jan 2019 19:32:09 +0300 Subject: [PATCH 1/2] [MSP430] Support of __[bic|bis]_SR_register_on_exit unsigned short __bic_SR_register_on_exit(unsigned short mask) unsigned short __bis_SR_register_on_exit(unsigned short mask) __bic_SR_register_on_exit clears and __bis_SR_register_on_exit sets the bits of saved copy of the status register, specified in the mask. The builtins are only available within interrupt handlers, an error is reported in other cases. Accepts: any unsigned short integer which specifies bits of the saved status register that need to be changed. Returns: the saved copy of the status register before the update. --- src/llvm/lib/Support/Triple.cpp | 2 ++ .../include/clang/Basic/BuiltinsMSP430.def | 19 +++++++++++++++++ .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ .../include/clang/Basic/TargetBuiltins.h | 10 +++++++++ .../tools/clang/include/clang/Sema/Sema.h | 1 + .../tools/clang/lib/Basic/Targets/MSP430.cpp | 12 +++++++++++ .../tools/clang/lib/Basic/Targets/MSP430.h | 6 ++---- .../tools/clang/lib/Sema/SemaChecking.cpp | 21 +++++++++++++++++++ .../clang/test/CodeGen/builtins-msp430.c | 11 ++++++++++ .../tools/clang/test/Sema/builtins-msp430.c | 14 +++++++++++++ 10 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 src/llvm/tools/clang/include/clang/Basic/BuiltinsMSP430.def create mode 100644 src/llvm/tools/clang/test/CodeGen/builtins-msp430.c create mode 100644 src/llvm/tools/clang/test/Sema/builtins-msp430.c diff --git a/src/llvm/lib/Support/Triple.cpp b/src/llvm/lib/Support/Triple.cpp index 26d9327f620..57af42b7705 100644 --- a/src/llvm/lib/Support/Triple.cpp +++ b/src/llvm/lib/Support/Triple.cpp @@ -101,6 +101,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) { case mips64: case mips64el: return "mips"; + case msp430: return "msp430"; + case hexagon: return "hexagon"; case amdgcn: return "amdgcn"; diff --git a/src/llvm/tools/clang/include/clang/Basic/BuiltinsMSP430.def b/src/llvm/tools/clang/include/clang/Basic/BuiltinsMSP430.def new file mode 100644 index 00000000000..d114a56aabc --- /dev/null +++ b/src/llvm/tools/clang/include/clang/Basic/BuiltinsMSP430.def @@ -0,0 +1,19 @@ +//===-- BuiltinsMips.def - Mips Builtin function database --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MIPS-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +// Add/subtract with optional saturation +BUILTIN(__bic_SR_register_on_exit, "UsUs", "") +BUILTIN(__bis_SR_register_on_exit, "UsUs", "") diff --git a/src/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/src/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index b71f65d146c..e4b309a8213 100644 --- a/src/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/src/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8309,6 +8309,8 @@ def err_hexagon_builtin_requires_hvx : Error< "builtin requires HVX">; def err_hexagon_builtin_unsupported_hvx : Error< "builtin is not supported on this version of HVX">; +def err_msp430_builtin_not_isr_caller : Error< + "builtin is only available within interrupt routines">; def err_builtin_target_unsupported : Error< "builtin is not supported on this target">; diff --git a/src/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/src/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h index ab4b1c43f7c..acc12773a8a 100644 --- a/src/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h +++ b/src/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h @@ -160,6 +160,16 @@ namespace clang { }; } + /// MSP430 builtins + namespace MSP430 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsMSP430.def" + LastTSBuiltin + }; + } + /// XCore builtins namespace XCore { enum { diff --git a/src/llvm/tools/clang/include/clang/Sema/Sema.h b/src/llvm/tools/clang/include/clang/Sema/Sema.h index e5b7465820a..2fe8fde998d 100644 --- a/src/llvm/tools/clang/include/clang/Sema/Sema.h +++ b/src/llvm/tools/clang/include/clang/Sema/Sema.h @@ -10514,6 +10514,7 @@ class Sema { bool CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, CallExpr *TheCall); bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckMSP430BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall); bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call); diff --git a/src/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp b/src/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp index 86f85a398f1..14c91334b95 100644 --- a/src/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp +++ b/src/llvm/tools/clang/lib/Basic/Targets/MSP430.cpp @@ -13,6 +13,7 @@ #include "MSP430.h" #include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/TargetBuiltins.h" using namespace clang; using namespace clang::targets; @@ -22,6 +23,17 @@ const char *const MSP430TargetInfo::GCCRegNames[] = { "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }; +const Builtin::Info MSP430TargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, +#include "clang/Basic/BuiltinsMSP430.def" +}; + +ArrayRef MSP430TargetInfo::getTargetBuiltins() const { + return llvm::makeArrayRef( + BuiltinInfo, clang::MSP430::LastTSBuiltin - Builtin::FirstTSBuiltin); +} + ArrayRef MSP430TargetInfo::getGCCRegNames() const { return llvm::makeArrayRef(GCCRegNames); } diff --git a/src/llvm/tools/clang/lib/Basic/Targets/MSP430.h b/src/llvm/tools/clang/lib/Basic/Targets/MSP430.h index 4ee54a371ac..b10c71f0ac1 100644 --- a/src/llvm/tools/clang/lib/Basic/Targets/MSP430.h +++ b/src/llvm/tools/clang/lib/Basic/Targets/MSP430.h @@ -24,6 +24,7 @@ namespace targets { class LLVM_LIBRARY_VISIBILITY MSP430TargetInfo : public TargetInfo { static const char *const GCCRegNames[]; + static const Builtin::Info BuiltinInfo[]; public: MSP430TargetInfo(const llvm::Triple &Triple, const TargetOptions &) @@ -48,10 +49,7 @@ class LLVM_LIBRARY_VISIBILITY MSP430TargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef getTargetBuiltins() const override { - // FIXME: Implement. - return None; - } + ArrayRef getTargetBuiltins() const override; bool allowsLargerPreferedTypeAlignment() const override { return false; } diff --git a/src/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/src/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 8dc1fdb7698..62abbd21bcb 100644 --- a/src/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/src/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -1475,6 +1475,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (CheckPPCBuiltinFunctionCall(BuiltinID, TheCall)) return ExprError(); break; + case llvm::Triple::msp430: + if (CheckMSP430BuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; default: break; } @@ -3919,6 +3923,23 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return SemaBuiltinConstantArgRange(TheCall, i, l, u, /*RangeIsError*/ false); } +bool Sema::CheckMSP430BuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + switch (BuiltinID) { + default: + return false; + case MSP430::BI__bic_SR_register_on_exit: + case MSP430::BI__bis_SR_register_on_exit: + auto *FD = cast(CurContext); + // These builtins can only be used inside interrupt handlers. + if (!FD->hasAttr()) + return + Diag(TheCall->getBeginLoc(), diag::err_msp430_builtin_not_isr_caller) + << TheCall->getSourceRange(); + } + return false; +} + /// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo /// parameter with the FormatAttr's correct format_idx and firstDataArg. /// Returns true when the format fits the function and the FormatStringInfo has diff --git a/src/llvm/tools/clang/test/CodeGen/builtins-msp430.c b/src/llvm/tools/clang/test/CodeGen/builtins-msp430.c new file mode 100644 index 00000000000..71ee33808ff --- /dev/null +++ b/src/llvm/tools/clang/test/CodeGen/builtins-msp430.c @@ -0,0 +1,11 @@ +// REQUIRES: msp430-registered-target +// RUN: %clang_cc1 -triple msp430-elf -emit-llvm -o - %s | FileCheck %s + +__attribute__((interrupt(1))) void foo(void) { +// CHECK: call i16 @llvm.msp430.bic.saved.status(i16 1) + __bic_SR_register_on_exit(1); + +// CHECK: call i16 @llvm.msp430.bis.saved.status(i16 1) + __bis_SR_register_on_exit(1); +} + diff --git a/src/llvm/tools/clang/test/Sema/builtins-msp430.c b/src/llvm/tools/clang/test/Sema/builtins-msp430.c new file mode 100644 index 00000000000..c96abac69d3 --- /dev/null +++ b/src/llvm/tools/clang/test/Sema/builtins-msp430.c @@ -0,0 +1,14 @@ +// REQUIRES: msp430-registered-target +// RUN: %clang_cc1 %s -triple msp430-elf -fsyntax-only -verify + +void f(void) { + __bic_SR_register_on_exit(1); // expected-error {{builtin is only available within interrupt routines}} + __bis_SR_register_on_exit(1); // expected-error {{builtin is only available within interrupt routines}} +} + +__attribute__((interrupt(1))) +void ISR(void) { + __bic_SR_register_on_exit(1); + __bis_SR_register_on_exit(1); +} + From 6ecb455a5e17ae39131100966d2c49fa3905015e Mon Sep 17 00:00:00 2001 From: Kristina Bessonova Date: Thu, 13 Dec 2018 16:25:44 +0300 Subject: [PATCH 2/2] [MSP430] Add @llvm.msp430.[bis|bic].status.on.exit intrinsics Add MSP430 specific intrinsics in order to support __bic_SR_register_on_exit and __bis_SR_register_on_exit builtins. --- src/llvm/include/llvm/IR/Intrinsics.td | 1 + src/llvm/include/llvm/IR/IntrinsicsMSP430.td | 21 ++++++++ .../lib/Target/MSP430/MSP430ISelLowering.cpp | 53 +++++++++++++++++++ .../lib/Target/MSP430/MSP430ISelLowering.h | 1 + .../Target/MSP430/MSP430MachineFunctionInfo.h | 10 +++- .../CodeGen/MSP430/bic_bis_saved_status.ll | 44 +++++++++++++++ 6 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/llvm/include/llvm/IR/IntrinsicsMSP430.td create mode 100644 src/llvm/test/CodeGen/MSP430/bic_bis_saved_status.ll diff --git a/src/llvm/include/llvm/IR/Intrinsics.td b/src/llvm/include/llvm/IR/Intrinsics.td index 64603d8ea03..7a2575377d6 100644 --- a/src/llvm/include/llvm/IR/Intrinsics.td +++ b/src/llvm/include/llvm/IR/Intrinsics.td @@ -1156,3 +1156,4 @@ include "llvm/IR/IntrinsicsBPF.td" include "llvm/IR/IntrinsicsSystemZ.td" include "llvm/IR/IntrinsicsWebAssembly.td" include "llvm/IR/IntrinsicsRISCV.td" +include "llvm/IR/IntrinsicsMSP430.td" diff --git a/src/llvm/include/llvm/IR/IntrinsicsMSP430.td b/src/llvm/include/llvm/IR/IntrinsicsMSP430.td new file mode 100644 index 00000000000..d663a6b8744 --- /dev/null +++ b/src/llvm/include/llvm/IR/IntrinsicsMSP430.td @@ -0,0 +1,21 @@ +//===- IntrinsicsMSP430.td - Defines MSP430 intrinsics -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the MSP430-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "msp430" in { // All intrinsics start with "llvm.msp430." + def int_msp430_bic_saved_status : + Intrinsic<[llvm_i16_ty], [llvm_i16_ty], []>, + GCCBuiltin<"__bic_SR_register_on_exit">; + def int_msp430_bis_saved_status : + Intrinsic<[llvm_i16_ty], [llvm_i16_ty], []>, + GCCBuiltin<"__bis_SR_register_on_exit">; +} diff --git a/src/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/src/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp index 3e706134afc..e69617ba01e 100644 --- a/src/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/src/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -146,6 +146,9 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM, setOperationAction(ISD::VACOPY, MVT::Other, Expand); setOperationAction(ISD::JumpTable, MVT::i16, Custom); + // Custom lowering for some intrinsics + setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); + // EABI Libcalls - EABI Section 6.2 const struct { const RTLIB::Libcall Op; @@ -349,6 +352,7 @@ SDValue MSP430TargetLowering::LowerOperation(SDValue Op, case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); + case ISD::INTRINSIC_W_CHAIN: return LowerINTRINSIC_W_CHAIN(Op, DAG); default: llvm_unreachable("unimplemented operand"); } @@ -938,6 +942,55 @@ SDValue MSP430TargetLowering::LowerCallResult( return Chain; } +SDValue MSP430TargetLowering:: +LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const { + unsigned IntNo = cast(Op.getOperand(1))->getZExtValue(); + switch (IntNo) { + default: + break; + case Intrinsic::msp430_bis_saved_status: + case Intrinsic::msp430_bic_saved_status: + MachineFunction &MF = DAG.getMachineFunction(); + MSP430MachineFunctionInfo *FuncInfo = + MF.getInfo(); + + int SavedSRFrameIndex = FuncInfo->getSavedSRIndex(); + if (SavedSRFrameIndex == 0) { + SavedSRFrameIndex = + MF.getFrameInfo().CreateFixedObject(/*Size*/ 2, /*Offset*/-2, true); + FuncInfo->setSavedSRIndex(SavedSRFrameIndex); + } + + MVT PtrVT = getPointerTy(DAG.getDataLayout()); + SDValue FI = DAG.getFrameIndex(SavedSRFrameIndex, PtrVT); + + SDValue Chain = Op->getOperand(0); + SDLoc DL(Op); + + // Load a saved copy of status register. + SDValue SR = + DAG.getLoad(MVT::i16, DL, Chain, FI, + MachinePointerInfo::getFixedStack(MF, SavedSRFrameIndex)); + + SDValue Result; + if (IntNo == Intrinsic::msp430_bis_saved_status) { + Result = DAG.getNode(ISD::OR, DL, MVT::i16, SR, Op->getOperand(2)); + } else { + // IntNo == Intrinsic::msp430_bic_saved_status + Result = DAG.getNOT(DL, Op->getOperand(2), MVT::i16); + Result = DAG.getNode(ISD::AND, DL, MVT::i16, SR, Result); + } + + // Store the result. + Chain = + DAG.getStore(SR.getValue(1), DL, Result, FI, + MachinePointerInfo::getFixedStack(MF, SavedSRFrameIndex)); + SDValue Ops[2] = { SR.getValue(0), Chain }; + return DAG.getMergeValues(Ops, DL); + } + return SDValue(); +} + SDValue MSP430TargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const { unsigned Opc = Op.getOpcode(); diff --git a/src/llvm/lib/Target/MSP430/MSP430ISelLowering.h b/src/llvm/lib/Target/MSP430/MSP430ISelLowering.h index 731bc140671..197fb964147 100644 --- a/src/llvm/lib/Target/MSP430/MSP430ISelLowering.h +++ b/src/llvm/lib/Target/MSP430/MSP430ISelLowering.h @@ -99,6 +99,7 @@ namespace llvm { SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const; TargetLowering::ConstraintType diff --git a/src/llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h b/src/llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h index fcaa8a1d6c7..fd1a68a9043 100644 --- a/src/llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h +++ b/src/llvm/lib/Target/MSP430/MSP430MachineFunctionInfo.h @@ -33,6 +33,10 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo { /// VarArgsFrameIndex - FrameIndex for start of varargs area. int VarArgsFrameIndex; + /// SavedSRFrameIndex - FrameIndex for saved copy of status register + /// (interrupt handlers only). + int SavedSRFrameIndex; + /// SRetReturnReg - Some subtargets require that sret lowering includes /// returning the value of the returned struct in a register. This field /// holds the virtual register into which the sret argument is passed. @@ -42,7 +46,8 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo { MSP430MachineFunctionInfo() : CalleeSavedFrameSize(0) {} explicit MSP430MachineFunctionInfo(MachineFunction &MF) - : CalleeSavedFrameSize(0), ReturnAddrIndex(0), SRetReturnReg(0) {} + : CalleeSavedFrameSize(0), ReturnAddrIndex(0), SavedSRFrameIndex(0), + SRetReturnReg(0) {} unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; } void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; } @@ -53,6 +58,9 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo { int getRAIndex() const { return ReturnAddrIndex; } void setRAIndex(int Index) { ReturnAddrIndex = Index; } + int getSavedSRIndex() const { return SavedSRFrameIndex; } + void setSavedSRIndex(int Index) { SavedSRFrameIndex = Index; } + int getVarArgsFrameIndex() const { return VarArgsFrameIndex;} void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } }; diff --git a/src/llvm/test/CodeGen/MSP430/bic_bis_saved_status.ll b/src/llvm/test/CodeGen/MSP430/bic_bis_saved_status.ll new file mode 100644 index 00000000000..a598351e77f --- /dev/null +++ b/src/llvm/test/CodeGen/MSP430/bic_bis_saved_status.ll @@ -0,0 +1,44 @@ +; RUN: llc < %s | FileCheck %s + +target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16" +target triple = "msp430-elf" + +define msp430_intrcc void @bis() #0 { +; CHECK-LABEL: bis: +; CHECK: bis #5, @r1 + %1 = call i16 @llvm.msp430.bis.saved.status(i16 5) + ret void +} + +@a = common dso_local local_unnamed_addr global i16 0, align 2 + +define msp430_intrcc void @bic() #0 { +; CHECK-LABEL: bic: +; CHECK: bic &a, @r1 + %1 = load i16, i16* @a, align 2 + %2 = call i16 @llvm.msp430.bic.saved.status(i16 %1) + ret void +} + +; Check that the intrinsic returns the value of the saved status register +; before the update. + +define dso_local msp430_intrcc void @foo() #0 { +; CHECK-LABEL: foo: +; CHECK: push r13 +; CHECK-NEXT: push r12 +; CHECK-NEXT: mov 4(r1), r12 +; CHECK-NEXT: mov r12, r13 +; CHECK-NEXT: bis #5, r13 +; CHECK-NEXT: mov r13, 4(r1) +; CHECK-NEXT: mov r12, &a + + %1 = tail call i16 @llvm.msp430.bis.saved.status(i16 5) + store i16 %1, i16* @a, align 2 + ret void +} + +declare i16 @llvm.msp430.bis.saved.status(i16) +declare i16 @llvm.msp430.bic.saved.status(i16) + +attributes #0 = {"interrupt"="1"}