PageRenderTime 68ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Sema/TargetAttributesSema.cpp

https://gitlab.com/wustl-pctg-pub/clang-cilk
C++ | 353 lines | 275 code | 39 blank | 39 comment | 62 complexity | 6a7e7cf605456e5432bbe856a19d955c MD5 | raw file
  1. //===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file contains semantic analysis implementation for target-specific
  11. // attributes.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "TargetAttributesSema.h"
  15. #include "clang/AST/DeclCXX.h"
  16. #include "clang/Basic/TargetInfo.h"
  17. #include "clang/Sema/SemaInternal.h"
  18. #include "llvm/ADT/Triple.h"
  19. using namespace clang;
  20. TargetAttributesSema::~TargetAttributesSema() {}
  21. bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
  22. const AttributeList &Attr, Sema &S) const {
  23. return false;
  24. }
  25. static void HandleARMInterruptAttr(Decl *d,
  26. const AttributeList &Attr, Sema &S) {
  27. // Check the attribute arguments.
  28. if (Attr.getNumArgs() > 1) {
  29. S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
  30. << 1;
  31. return;
  32. }
  33. StringRef Str;
  34. SourceLocation ArgLoc;
  35. if (Attr.getNumArgs() == 0)
  36. Str = "";
  37. else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
  38. return;
  39. ARMInterruptAttr::InterruptType Kind;
  40. if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
  41. S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
  42. << Attr.getName() << Str << ArgLoc;
  43. return;
  44. }
  45. unsigned Index = Attr.getAttributeSpellingListIndex();
  46. d->addAttr(::new (S.Context)
  47. ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
  48. }
  49. namespace {
  50. class ARMAttributesSema : public TargetAttributesSema {
  51. public:
  52. ARMAttributesSema() { }
  53. bool ProcessDeclAttribute(Scope *scope, Decl *D,
  54. const AttributeList &Attr, Sema &S) const {
  55. if (Attr.getName()->getName() == "interrupt") {
  56. HandleARMInterruptAttr(D, Attr, S);
  57. return true;
  58. }
  59. return false;
  60. }
  61. };
  62. }
  63. static void HandleMSP430InterruptAttr(Decl *d,
  64. const AttributeList &Attr, Sema &S) {
  65. // Check the attribute arguments.
  66. if (Attr.getNumArgs() != 1) {
  67. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
  68. << Attr.getName() << 1;
  69. return;
  70. }
  71. // FIXME: Check for decl - it should be void ()(void).
  72. Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
  73. llvm::APSInt NumParams(32);
  74. if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
  75. S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
  76. << Attr.getName() << AANT_ArgumentIntegerConstant
  77. << NumParamsExpr->getSourceRange();
  78. return;
  79. }
  80. unsigned Num = NumParams.getLimitedValue(255);
  81. if ((Num & 1) || Num > 30) {
  82. S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
  83. << "interrupt" << (int)NumParams.getSExtValue()
  84. << NumParamsExpr->getSourceRange();
  85. return;
  86. }
  87. d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
  88. d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
  89. }
  90. namespace {
  91. class MSP430AttributesSema : public TargetAttributesSema {
  92. public:
  93. MSP430AttributesSema() { }
  94. bool ProcessDeclAttribute(Scope *scope, Decl *D,
  95. const AttributeList &Attr, Sema &S) const {
  96. if (Attr.getName()->getName() == "interrupt") {
  97. HandleMSP430InterruptAttr(D, Attr, S);
  98. return true;
  99. }
  100. return false;
  101. }
  102. };
  103. }
  104. static void HandleX86ForceAlignArgPointerAttr(Decl *D,
  105. const AttributeList& Attr,
  106. Sema &S) {
  107. // Check the attribute arguments.
  108. if (Attr.getNumArgs() != 0) {
  109. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
  110. << Attr.getName() << 0;
  111. return;
  112. }
  113. // If we try to apply it to a function pointer, don't warn, but don't
  114. // do anything, either. It doesn't matter anyway, because there's nothing
  115. // special about calling a force_align_arg_pointer function.
  116. ValueDecl *VD = dyn_cast<ValueDecl>(D);
  117. if (VD && VD->getType()->isFunctionPointerType())
  118. return;
  119. // Also don't warn on function pointer typedefs.
  120. TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
  121. if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
  122. TD->getUnderlyingType()->isFunctionType()))
  123. return;
  124. // Attribute can only be applied to function types.
  125. if (!isa<FunctionDecl>(D)) {
  126. S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
  127. << Attr.getName() << /* function */0;
  128. return;
  129. }
  130. D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getRange(),
  131. S.Context));
  132. }
  133. DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
  134. unsigned AttrSpellingListIndex) {
  135. if (D->hasAttr<DLLExportAttr>()) {
  136. Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
  137. return NULL;
  138. }
  139. if (D->hasAttr<DLLImportAttr>())
  140. return NULL;
  141. if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
  142. if (VD->hasDefinition()) {
  143. // dllimport cannot be applied to definitions.
  144. Diag(D->getLocation(), diag::warn_attribute_invalid_on_definition)
  145. << "dllimport";
  146. return NULL;
  147. }
  148. }
  149. return ::new (Context) DLLImportAttr(Range, Context,
  150. AttrSpellingListIndex);
  151. }
  152. static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
  153. // check the attribute arguments.
  154. if (Attr.getNumArgs() != 0) {
  155. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
  156. << Attr.getName() << 0;
  157. return;
  158. }
  159. // Attribute can be applied only to functions or variables.
  160. FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
  161. if (!FD && !isa<VarDecl>(D)) {
  162. // Apparently Visual C++ thinks it is okay to not emit a warning
  163. // in this case, so only emit a warning when -fms-extensions is not
  164. // specified.
  165. if (!S.getLangOpts().MicrosoftExt)
  166. S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
  167. << Attr.getName() << 2 /*variable and function*/;
  168. return;
  169. }
  170. // Currently, the dllimport attribute is ignored for inlined functions.
  171. // Warning is emitted.
  172. if (FD && FD->isInlineSpecified()) {
  173. S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
  174. return;
  175. }
  176. unsigned Index = Attr.getAttributeSpellingListIndex();
  177. DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
  178. if (NewAttr)
  179. D->addAttr(NewAttr);
  180. }
  181. DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
  182. unsigned AttrSpellingListIndex) {
  183. if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
  184. Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
  185. D->dropAttr<DLLImportAttr>();
  186. }
  187. if (D->hasAttr<DLLExportAttr>())
  188. return NULL;
  189. return ::new (Context) DLLExportAttr(Range, Context,
  190. AttrSpellingListIndex);
  191. }
  192. static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
  193. // check the attribute arguments.
  194. if (Attr.getNumArgs() != 0) {
  195. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
  196. << Attr.getName() << 0;
  197. return;
  198. }
  199. // Attribute can be applied only to functions or variables.
  200. FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
  201. if (!FD && !isa<VarDecl>(D)) {
  202. S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
  203. << Attr.getName() << 2 /*variable and function*/;
  204. return;
  205. }
  206. // Currently, the dllexport attribute is ignored for inlined functions, unless
  207. // the -fkeep-inline-functions flag has been used. Warning is emitted;
  208. if (FD && FD->isInlineSpecified()) {
  209. // FIXME: ... unless the -fkeep-inline-functions flag has been used.
  210. S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
  211. return;
  212. }
  213. unsigned Index = Attr.getAttributeSpellingListIndex();
  214. DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
  215. if (NewAttr)
  216. D->addAttr(NewAttr);
  217. }
  218. namespace {
  219. class X86AttributesSema : public TargetAttributesSema {
  220. public:
  221. X86AttributesSema() { }
  222. bool ProcessDeclAttribute(Scope *scope, Decl *D,
  223. const AttributeList &Attr, Sema &S) const {
  224. const llvm::Triple &Triple(S.Context.getTargetInfo().getTriple());
  225. if (Triple.getOS() == llvm::Triple::Win32 ||
  226. Triple.getOS() == llvm::Triple::MinGW32) {
  227. switch (Attr.getKind()) {
  228. case AttributeList::AT_DLLImport: HandleDLLImportAttr(D, Attr, S);
  229. return true;
  230. case AttributeList::AT_DLLExport: HandleDLLExportAttr(D, Attr, S);
  231. return true;
  232. default: break;
  233. }
  234. }
  235. if (Triple.getArch() != llvm::Triple::x86_64 &&
  236. (Attr.getName()->getName() == "force_align_arg_pointer" ||
  237. Attr.getName()->getName() == "__force_align_arg_pointer__")) {
  238. HandleX86ForceAlignArgPointerAttr(D, Attr, S);
  239. return true;
  240. }
  241. return false;
  242. }
  243. };
  244. }
  245. static void HandleMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
  246. // check the attribute arguments.
  247. if (Attr.getNumArgs()) {
  248. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
  249. << Attr.getName() << 0;
  250. return;
  251. }
  252. // Attribute can only be applied to function types.
  253. if (!isa<FunctionDecl>(D)) {
  254. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
  255. << Attr.getName() << /* function */0;
  256. return;
  257. }
  258. D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context,
  259. Attr.getAttributeSpellingListIndex()));
  260. }
  261. static void HandleNoMips16Attr(Decl *D, const AttributeList &Attr, Sema &S) {
  262. // check the attribute arguments.
  263. if (Attr.getNumArgs()) {
  264. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
  265. << Attr.getName() << 0;
  266. return;
  267. }
  268. // Attribute can only be applied to function types.
  269. if (!isa<FunctionDecl>(D)) {
  270. S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
  271. << Attr.getName() << /* function */0;
  272. return;
  273. }
  274. D->addAttr(::new (S.Context)
  275. NoMips16Attr(Attr.getRange(), S.Context,
  276. Attr.getAttributeSpellingListIndex()));
  277. }
  278. namespace {
  279. class MipsAttributesSema : public TargetAttributesSema {
  280. public:
  281. MipsAttributesSema() { }
  282. bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr,
  283. Sema &S) const {
  284. if (Attr.getName()->getName() == "mips16") {
  285. HandleMips16Attr(D, Attr, S);
  286. return true;
  287. } else if (Attr.getName()->getName() == "nomips16") {
  288. HandleNoMips16Attr(D, Attr, S);
  289. return true;
  290. }
  291. return false;
  292. }
  293. };
  294. }
  295. const TargetAttributesSema &Sema::getTargetAttributesSema() const {
  296. if (TheTargetAttributesSema)
  297. return *TheTargetAttributesSema;
  298. const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
  299. switch (Triple.getArch()) {
  300. case llvm::Triple::arm:
  301. case llvm::Triple::thumb:
  302. return *(TheTargetAttributesSema = new ARMAttributesSema);
  303. case llvm::Triple::msp430:
  304. return *(TheTargetAttributesSema = new MSP430AttributesSema);
  305. case llvm::Triple::x86:
  306. case llvm::Triple::x86_64:
  307. return *(TheTargetAttributesSema = new X86AttributesSema);
  308. case llvm::Triple::mips:
  309. case llvm::Triple::mipsel:
  310. return *(TheTargetAttributesSema = new MipsAttributesSema);
  311. default:
  312. return *(TheTargetAttributesSema = new TargetAttributesSema);
  313. }
  314. }