1//===------ SemaMSP430.cpp ----- MSP430 target-specific routines ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis functions specific to NVPTX.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Sema/SemaMSP430.h"
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/Attr.h"
16#include "clang/AST/DeclBase.h"
17#include "clang/Basic/DiagnosticSema.h"
18#include "clang/Sema/Attr.h"
19#include "clang/Sema/ParsedAttr.h"
20
21namespace clang {
22
23SemaMSP430::SemaMSP430(Sema &S) : SemaBase(S) {}
24
25void SemaMSP430::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
26 // MSP430 'interrupt' attribute is applied to
27 // a function with no parameters and void return type.
28 if (!isFuncOrMethodForAttrSubject(D)) {
29 Diag(Loc: D->getLocation(), DiagID: diag::warn_attribute_wrong_decl_type)
30 << AL << AL.isRegularKeywordAttribute() << ExpectedFunctionOrMethod;
31 return;
32 }
33
34 if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
35 Diag(Loc: D->getLocation(), DiagID: diag::warn_interrupt_attribute_invalid)
36 << /*MSP430*/ 1 << 0;
37 return;
38 }
39
40 if (!getFunctionOrMethodResultType(D)->isVoidType()) {
41 Diag(Loc: D->getLocation(), DiagID: diag::warn_interrupt_attribute_invalid)
42 << /*MSP430*/ 1 << 1;
43 return;
44 }
45
46 // The attribute takes one integer argument.
47 if (!AL.checkExactlyNumArgs(S&: SemaRef, Num: 1))
48 return;
49
50 if (!AL.isArgExpr(Arg: 0)) {
51 Diag(Loc: AL.getLoc(), DiagID: diag::err_attribute_argument_type)
52 << AL << AANT_ArgumentIntegerConstant;
53 return;
54 }
55
56 Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(Arg: 0));
57 std::optional<llvm::APSInt> NumParams = llvm::APSInt(32);
58 if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(Ctx: getASTContext()))) {
59 Diag(Loc: AL.getLoc(), DiagID: diag::err_attribute_argument_type)
60 << AL << AANT_ArgumentIntegerConstant
61 << NumParamsExpr->getSourceRange();
62 return;
63 }
64 // The argument should be in range 0..63.
65 unsigned Num = NumParams->getLimitedValue(Limit: 255);
66 if (Num > 63) {
67 Diag(Loc: AL.getLoc(), DiagID: diag::err_attribute_argument_out_of_bounds)
68 << AL << (int)NumParams->getSExtValue()
69 << NumParamsExpr->getSourceRange();
70 return;
71 }
72
73 D->addAttr(A: ::new (getASTContext())
74 MSP430InterruptAttr(getASTContext(), AL, Num));
75 D->addAttr(A: UsedAttr::CreateImplicit(Ctx&: getASTContext()));
76}
77
78} // namespace clang
79