SemaStmtAsm.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. //===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
  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 for inline asm statements.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/AST/ExprCXX.h"
  13. #include "clang/AST/GlobalDecl.h"
  14. #include "clang/AST/RecordLayout.h"
  15. #include "clang/AST/TypeLoc.h"
  16. #include "clang/Basic/TargetInfo.h"
  17. #include "clang/Lex/Preprocessor.h"
  18. #include "clang/Sema/Initialization.h"
  19. #include "clang/Sema/Lookup.h"
  20. #include "clang/Sema/Scope.h"
  21. #include "clang/Sema/ScopeInfo.h"
  22. #include "clang/Sema/SemaInternal.h"
  23. #include "llvm/ADT/ArrayRef.h"
  24. #include "llvm/ADT/StringSet.h"
  25. #include "llvm/MC/MCParser/MCAsmParser.h"
  26. #include <optional>
  27. using namespace clang;
  28. using namespace sema;
  29. /// Remove the upper-level LValueToRValue cast from an expression.
  30. static void removeLValueToRValueCast(Expr *E) {
  31. Expr *Parent = E;
  32. Expr *ExprUnderCast = nullptr;
  33. SmallVector<Expr *, 8> ParentsToUpdate;
  34. while (true) {
  35. ParentsToUpdate.push_back(Parent);
  36. if (auto *ParenE = dyn_cast<ParenExpr>(Parent)) {
  37. Parent = ParenE->getSubExpr();
  38. continue;
  39. }
  40. Expr *Child = nullptr;
  41. CastExpr *ParentCast = dyn_cast<CastExpr>(Parent);
  42. if (ParentCast)
  43. Child = ParentCast->getSubExpr();
  44. else
  45. return;
  46. if (auto *CastE = dyn_cast<CastExpr>(Child))
  47. if (CastE->getCastKind() == CK_LValueToRValue) {
  48. ExprUnderCast = CastE->getSubExpr();
  49. // LValueToRValue cast inside GCCAsmStmt requires an explicit cast.
  50. ParentCast->setSubExpr(ExprUnderCast);
  51. break;
  52. }
  53. Parent = Child;
  54. }
  55. // Update parent expressions to have same ValueType as the underlying.
  56. assert(ExprUnderCast &&
  57. "Should be reachable only if LValueToRValue cast was found!");
  58. auto ValueKind = ExprUnderCast->getValueKind();
  59. for (Expr *E : ParentsToUpdate)
  60. E->setValueKind(ValueKind);
  61. }
  62. /// Emit a warning about usage of "noop"-like casts for lvalues (GNU extension)
  63. /// and fix the argument with removing LValueToRValue cast from the expression.
  64. static void emitAndFixInvalidAsmCastLValue(const Expr *LVal, Expr *BadArgument,
  65. Sema &S) {
  66. if (!S.getLangOpts().HeinousExtensions) {
  67. S.Diag(LVal->getBeginLoc(), diag::err_invalid_asm_cast_lvalue)
  68. << BadArgument->getSourceRange();
  69. } else {
  70. S.Diag(LVal->getBeginLoc(), diag::warn_invalid_asm_cast_lvalue)
  71. << BadArgument->getSourceRange();
  72. }
  73. removeLValueToRValueCast(BadArgument);
  74. }
  75. /// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
  76. /// ignore "noop" casts in places where an lvalue is required by an inline asm.
  77. /// We emulate this behavior when -fheinous-gnu-extensions is specified, but
  78. /// provide a strong guidance to not use it.
  79. ///
  80. /// This method checks to see if the argument is an acceptable l-value and
  81. /// returns false if it is a case we can handle.
  82. static bool CheckAsmLValue(Expr *E, Sema &S) {
  83. // Type dependent expressions will be checked during instantiation.
  84. if (E->isTypeDependent())
  85. return false;
  86. if (E->isLValue())
  87. return false; // Cool, this is an lvalue.
  88. // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
  89. // are supposed to allow.
  90. const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
  91. if (E != E2 && E2->isLValue()) {
  92. emitAndFixInvalidAsmCastLValue(E2, E, S);
  93. // Accept, even if we emitted an error diagnostic.
  94. return false;
  95. }
  96. // None of the above, just randomly invalid non-lvalue.
  97. return true;
  98. }
  99. /// isOperandMentioned - Return true if the specified operand # is mentioned
  100. /// anywhere in the decomposed asm string.
  101. static bool
  102. isOperandMentioned(unsigned OpNo,
  103. ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
  104. for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
  105. const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
  106. if (!Piece.isOperand())
  107. continue;
  108. // If this is a reference to the input and if the input was the smaller
  109. // one, then we have to reject this asm.
  110. if (Piece.getOperandNo() == OpNo)
  111. return true;
  112. }
  113. return false;
  114. }
  115. static bool CheckNakedParmReference(Expr *E, Sema &S) {
  116. FunctionDecl *Func = dyn_cast<FunctionDecl>(S.CurContext);
  117. if (!Func)
  118. return false;
  119. if (!Func->hasAttr<NakedAttr>())
  120. return false;
  121. SmallVector<Expr*, 4> WorkList;
  122. WorkList.push_back(E);
  123. while (WorkList.size()) {
  124. Expr *E = WorkList.pop_back_val();
  125. if (isa<CXXThisExpr>(E)) {
  126. S.Diag(E->getBeginLoc(), diag::err_asm_naked_this_ref);
  127. S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
  128. return true;
  129. }
  130. if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
  131. if (isa<ParmVarDecl>(DRE->getDecl())) {
  132. S.Diag(DRE->getBeginLoc(), diag::err_asm_naked_parm_ref);
  133. S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
  134. return true;
  135. }
  136. }
  137. for (Stmt *Child : E->children()) {
  138. if (Expr *E = dyn_cast_or_null<Expr>(Child))
  139. WorkList.push_back(E);
  140. }
  141. }
  142. return false;
  143. }
  144. /// Returns true if given expression is not compatible with inline
  145. /// assembly's memory constraint; false otherwise.
  146. static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
  147. TargetInfo::ConstraintInfo &Info,
  148. bool is_input_expr) {
  149. enum {
  150. ExprBitfield = 0,
  151. ExprVectorElt,
  152. ExprGlobalRegVar,
  153. ExprSafeType
  154. } EType = ExprSafeType;
  155. // Bitfields, vector elements and global register variables are not
  156. // compatible.
  157. if (E->refersToBitField())
  158. EType = ExprBitfield;
  159. else if (E->refersToVectorElement())
  160. EType = ExprVectorElt;
  161. else if (E->refersToGlobalRegisterVar())
  162. EType = ExprGlobalRegVar;
  163. if (EType != ExprSafeType) {
  164. S.Diag(E->getBeginLoc(), diag::err_asm_non_addr_value_in_memory_constraint)
  165. << EType << is_input_expr << Info.getConstraintStr()
  166. << E->getSourceRange();
  167. return true;
  168. }
  169. return false;
  170. }
  171. // Extracting the register name from the Expression value,
  172. // if there is no register name to extract, returns ""
  173. static StringRef extractRegisterName(const Expr *Expression,
  174. const TargetInfo &Target) {
  175. Expression = Expression->IgnoreImpCasts();
  176. if (const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(Expression)) {
  177. // Handle cases where the expression is a variable
  178. const VarDecl *Variable = dyn_cast<VarDecl>(AsmDeclRef->getDecl());
  179. if (Variable && Variable->getStorageClass() == SC_Register) {
  180. if (AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>())
  181. if (Target.isValidGCCRegisterName(Attr->getLabel()))
  182. return Target.getNormalizedGCCRegisterName(Attr->getLabel(), true);
  183. }
  184. }
  185. return "";
  186. }
  187. // Checks if there is a conflict between the input and output lists with the
  188. // clobbers list. If there's a conflict, returns the location of the
  189. // conflicted clobber, else returns nullptr
  190. static SourceLocation
  191. getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
  192. StringLiteral **Clobbers, int NumClobbers,
  193. unsigned NumLabels,
  194. const TargetInfo &Target, ASTContext &Cont) {
  195. llvm::StringSet<> InOutVars;
  196. // Collect all the input and output registers from the extended asm
  197. // statement in order to check for conflicts with the clobber list
  198. for (unsigned int i = 0; i < Exprs.size() - NumLabels; ++i) {
  199. StringRef Constraint = Constraints[i]->getString();
  200. StringRef InOutReg = Target.getConstraintRegister(
  201. Constraint, extractRegisterName(Exprs[i], Target));
  202. if (InOutReg != "")
  203. InOutVars.insert(InOutReg);
  204. }
  205. // Check for each item in the clobber list if it conflicts with the input
  206. // or output
  207. for (int i = 0; i < NumClobbers; ++i) {
  208. StringRef Clobber = Clobbers[i]->getString();
  209. // We only check registers, therefore we don't check cc and memory
  210. // clobbers
  211. if (Clobber == "cc" || Clobber == "memory" || Clobber == "unwind")
  212. continue;
  213. Clobber = Target.getNormalizedGCCRegisterName(Clobber, true);
  214. // Go over the output's registers we collected
  215. if (InOutVars.count(Clobber))
  216. return Clobbers[i]->getBeginLoc();
  217. }
  218. return SourceLocation();
  219. }
  220. StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
  221. bool IsVolatile, unsigned NumOutputs,
  222. unsigned NumInputs, IdentifierInfo **Names,
  223. MultiExprArg constraints, MultiExprArg Exprs,
  224. Expr *asmString, MultiExprArg clobbers,
  225. unsigned NumLabels,
  226. SourceLocation RParenLoc) {
  227. unsigned NumClobbers = clobbers.size();
  228. StringLiteral **Constraints =
  229. reinterpret_cast<StringLiteral**>(constraints.data());
  230. StringLiteral *AsmString = cast<StringLiteral>(asmString);
  231. StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
  232. SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
  233. // The parser verifies that there is a string literal here.
  234. assert(AsmString->isOrdinary());
  235. FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
  236. llvm::StringMap<bool> FeatureMap;
  237. Context.getFunctionFeatureMap(FeatureMap, FD);
  238. for (unsigned i = 0; i != NumOutputs; i++) {
  239. StringLiteral *Literal = Constraints[i];
  240. assert(Literal->isOrdinary());
  241. StringRef OutputName;
  242. if (Names[i])
  243. OutputName = Names[i]->getName();
  244. TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
  245. if (!Context.getTargetInfo().validateOutputConstraint(Info)) {
  246. targetDiag(Literal->getBeginLoc(),
  247. diag::err_asm_invalid_output_constraint)
  248. << Info.getConstraintStr();
  249. return new (Context)
  250. GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
  251. NumInputs, Names, Constraints, Exprs.data(), AsmString,
  252. NumClobbers, Clobbers, NumLabels, RParenLoc);
  253. }
  254. ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
  255. if (ER.isInvalid())
  256. return StmtError();
  257. Exprs[i] = ER.get();
  258. // Check that the output exprs are valid lvalues.
  259. Expr *OutputExpr = Exprs[i];
  260. // Referring to parameters is not allowed in naked functions.
  261. if (CheckNakedParmReference(OutputExpr, *this))
  262. return StmtError();
  263. // Check that the output expression is compatible with memory constraint.
  264. if (Info.allowsMemory() &&
  265. checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
  266. return StmtError();
  267. // Disallow bit-precise integer types, since the backends tend to have
  268. // difficulties with abnormal sizes.
  269. if (OutputExpr->getType()->isBitIntType())
  270. return StmtError(
  271. Diag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_type)
  272. << OutputExpr->getType() << 0 /*Input*/
  273. << OutputExpr->getSourceRange());
  274. OutputConstraintInfos.push_back(Info);
  275. // If this is dependent, just continue.
  276. if (OutputExpr->isTypeDependent())
  277. continue;
  278. Expr::isModifiableLvalueResult IsLV =
  279. OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
  280. switch (IsLV) {
  281. case Expr::MLV_Valid:
  282. // Cool, this is an lvalue.
  283. break;
  284. case Expr::MLV_ArrayType:
  285. // This is OK too.
  286. break;
  287. case Expr::MLV_LValueCast: {
  288. const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
  289. emitAndFixInvalidAsmCastLValue(LVal, OutputExpr, *this);
  290. // Accept, even if we emitted an error diagnostic.
  291. break;
  292. }
  293. case Expr::MLV_IncompleteType:
  294. case Expr::MLV_IncompleteVoidType:
  295. if (RequireCompleteType(OutputExpr->getBeginLoc(), Exprs[i]->getType(),
  296. diag::err_dereference_incomplete_type))
  297. return StmtError();
  298. [[fallthrough]];
  299. default:
  300. return StmtError(Diag(OutputExpr->getBeginLoc(),
  301. diag::err_asm_invalid_lvalue_in_output)
  302. << OutputExpr->getSourceRange());
  303. }
  304. unsigned Size = Context.getTypeSize(OutputExpr->getType());
  305. if (!Context.getTargetInfo().validateOutputSize(
  306. FeatureMap, Literal->getString(), Size)) {
  307. targetDiag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_output_size)
  308. << Info.getConstraintStr();
  309. return new (Context)
  310. GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
  311. NumInputs, Names, Constraints, Exprs.data(), AsmString,
  312. NumClobbers, Clobbers, NumLabels, RParenLoc);
  313. }
  314. }
  315. SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
  316. for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
  317. StringLiteral *Literal = Constraints[i];
  318. assert(Literal->isOrdinary());
  319. StringRef InputName;
  320. if (Names[i])
  321. InputName = Names[i]->getName();
  322. TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
  323. if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
  324. Info)) {
  325. targetDiag(Literal->getBeginLoc(), diag::err_asm_invalid_input_constraint)
  326. << Info.getConstraintStr();
  327. return new (Context)
  328. GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
  329. NumInputs, Names, Constraints, Exprs.data(), AsmString,
  330. NumClobbers, Clobbers, NumLabels, RParenLoc);
  331. }
  332. ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
  333. if (ER.isInvalid())
  334. return StmtError();
  335. Exprs[i] = ER.get();
  336. Expr *InputExpr = Exprs[i];
  337. if (InputExpr->getType()->isMemberPointerType())
  338. return StmtError(Diag(InputExpr->getBeginLoc(),
  339. diag::err_asm_pmf_through_constraint_not_permitted)
  340. << InputExpr->getSourceRange());
  341. // Referring to parameters is not allowed in naked functions.
  342. if (CheckNakedParmReference(InputExpr, *this))
  343. return StmtError();
  344. // Check that the input expression is compatible with memory constraint.
  345. if (Info.allowsMemory() &&
  346. checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
  347. return StmtError();
  348. // Only allow void types for memory constraints.
  349. if (Info.allowsMemory() && !Info.allowsRegister()) {
  350. if (CheckAsmLValue(InputExpr, *this))
  351. return StmtError(Diag(InputExpr->getBeginLoc(),
  352. diag::err_asm_invalid_lvalue_in_input)
  353. << Info.getConstraintStr()
  354. << InputExpr->getSourceRange());
  355. } else {
  356. ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
  357. if (Result.isInvalid())
  358. return StmtError();
  359. InputExpr = Exprs[i] = Result.get();
  360. if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
  361. if (!InputExpr->isValueDependent()) {
  362. Expr::EvalResult EVResult;
  363. if (InputExpr->EvaluateAsRValue(EVResult, Context, true)) {
  364. // For compatibility with GCC, we also allow pointers that would be
  365. // integral constant expressions if they were cast to int.
  366. llvm::APSInt IntResult;
  367. if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
  368. Context))
  369. if (!Info.isValidAsmImmediate(IntResult))
  370. return StmtError(
  371. Diag(InputExpr->getBeginLoc(),
  372. diag::err_invalid_asm_value_for_constraint)
  373. << toString(IntResult, 10) << Info.getConstraintStr()
  374. << InputExpr->getSourceRange());
  375. }
  376. }
  377. }
  378. }
  379. if (Info.allowsRegister()) {
  380. if (InputExpr->getType()->isVoidType()) {
  381. return StmtError(
  382. Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_type_in_input)
  383. << InputExpr->getType() << Info.getConstraintStr()
  384. << InputExpr->getSourceRange());
  385. }
  386. }
  387. if (InputExpr->getType()->isBitIntType())
  388. return StmtError(
  389. Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_type)
  390. << InputExpr->getType() << 1 /*Output*/
  391. << InputExpr->getSourceRange());
  392. InputConstraintInfos.push_back(Info);
  393. const Type *Ty = Exprs[i]->getType().getTypePtr();
  394. if (Ty->isDependentType())
  395. continue;
  396. if (!Ty->isVoidType() || !Info.allowsMemory())
  397. if (RequireCompleteType(InputExpr->getBeginLoc(), Exprs[i]->getType(),
  398. diag::err_dereference_incomplete_type))
  399. return StmtError();
  400. unsigned Size = Context.getTypeSize(Ty);
  401. if (!Context.getTargetInfo().validateInputSize(FeatureMap,
  402. Literal->getString(), Size))
  403. return targetDiag(InputExpr->getBeginLoc(),
  404. diag::err_asm_invalid_input_size)
  405. << Info.getConstraintStr();
  406. }
  407. std::optional<SourceLocation> UnwindClobberLoc;
  408. // Check that the clobbers are valid.
  409. for (unsigned i = 0; i != NumClobbers; i++) {
  410. StringLiteral *Literal = Clobbers[i];
  411. assert(Literal->isOrdinary());
  412. StringRef Clobber = Literal->getString();
  413. if (!Context.getTargetInfo().isValidClobber(Clobber)) {
  414. targetDiag(Literal->getBeginLoc(), diag::err_asm_unknown_register_name)
  415. << Clobber;
  416. return new (Context)
  417. GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
  418. NumInputs, Names, Constraints, Exprs.data(), AsmString,
  419. NumClobbers, Clobbers, NumLabels, RParenLoc);
  420. }
  421. if (Clobber == "unwind") {
  422. UnwindClobberLoc = Literal->getBeginLoc();
  423. }
  424. }
  425. // Using unwind clobber and asm-goto together is not supported right now.
  426. if (UnwindClobberLoc && NumLabels > 0) {
  427. targetDiag(*UnwindClobberLoc, diag::err_asm_unwind_and_goto);
  428. return new (Context)
  429. GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs,
  430. Names, Constraints, Exprs.data(), AsmString, NumClobbers,
  431. Clobbers, NumLabels, RParenLoc);
  432. }
  433. GCCAsmStmt *NS =
  434. new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
  435. NumInputs, Names, Constraints, Exprs.data(),
  436. AsmString, NumClobbers, Clobbers, NumLabels,
  437. RParenLoc);
  438. // Validate the asm string, ensuring it makes sense given the operands we
  439. // have.
  440. SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
  441. unsigned DiagOffs;
  442. if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
  443. targetDiag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
  444. << AsmString->getSourceRange();
  445. return NS;
  446. }
  447. // Validate constraints and modifiers.
  448. for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
  449. GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
  450. if (!Piece.isOperand()) continue;
  451. // Look for the correct constraint index.
  452. unsigned ConstraintIdx = Piece.getOperandNo();
  453. unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();
  454. // Labels are the last in the Exprs list.
  455. if (NS->isAsmGoto() && ConstraintIdx >= NumOperands)
  456. continue;
  457. // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
  458. // modifier '+'.
  459. if (ConstraintIdx >= NumOperands) {
  460. unsigned I = 0, E = NS->getNumOutputs();
  461. for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
  462. if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
  463. ConstraintIdx = I;
  464. break;
  465. }
  466. assert(I != E && "Invalid operand number should have been caught in "
  467. " AnalyzeAsmString");
  468. }
  469. // Now that we have the right indexes go ahead and check.
  470. StringLiteral *Literal = Constraints[ConstraintIdx];
  471. const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
  472. if (Ty->isDependentType() || Ty->isIncompleteType())
  473. continue;
  474. unsigned Size = Context.getTypeSize(Ty);
  475. std::string SuggestedModifier;
  476. if (!Context.getTargetInfo().validateConstraintModifier(
  477. Literal->getString(), Piece.getModifier(), Size,
  478. SuggestedModifier)) {
  479. targetDiag(Exprs[ConstraintIdx]->getBeginLoc(),
  480. diag::warn_asm_mismatched_size_modifier);
  481. if (!SuggestedModifier.empty()) {
  482. auto B = targetDiag(Piece.getRange().getBegin(),
  483. diag::note_asm_missing_constraint_modifier)
  484. << SuggestedModifier;
  485. SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
  486. B << FixItHint::CreateReplacement(Piece.getRange(), SuggestedModifier);
  487. }
  488. }
  489. }
  490. // Validate tied input operands for type mismatches.
  491. unsigned NumAlternatives = ~0U;
  492. for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
  493. TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
  494. StringRef ConstraintStr = Info.getConstraintStr();
  495. unsigned AltCount = ConstraintStr.count(',') + 1;
  496. if (NumAlternatives == ~0U) {
  497. NumAlternatives = AltCount;
  498. } else if (NumAlternatives != AltCount) {
  499. targetDiag(NS->getOutputExpr(i)->getBeginLoc(),
  500. diag::err_asm_unexpected_constraint_alternatives)
  501. << NumAlternatives << AltCount;
  502. return NS;
  503. }
  504. }
  505. SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(),
  506. ~0U);
  507. for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
  508. TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
  509. StringRef ConstraintStr = Info.getConstraintStr();
  510. unsigned AltCount = ConstraintStr.count(',') + 1;
  511. if (NumAlternatives == ~0U) {
  512. NumAlternatives = AltCount;
  513. } else if (NumAlternatives != AltCount) {
  514. targetDiag(NS->getInputExpr(i)->getBeginLoc(),
  515. diag::err_asm_unexpected_constraint_alternatives)
  516. << NumAlternatives << AltCount;
  517. return NS;
  518. }
  519. // If this is a tied constraint, verify that the output and input have
  520. // either exactly the same type, or that they are int/ptr operands with the
  521. // same size (int/long, int*/long, are ok etc).
  522. if (!Info.hasTiedOperand()) continue;
  523. unsigned TiedTo = Info.getTiedOperand();
  524. unsigned InputOpNo = i+NumOutputs;
  525. Expr *OutputExpr = Exprs[TiedTo];
  526. Expr *InputExpr = Exprs[InputOpNo];
  527. // Make sure no more than one input constraint matches each output.
  528. assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
  529. if (InputMatchedToOutput[TiedTo] != ~0U) {
  530. targetDiag(NS->getInputExpr(i)->getBeginLoc(),
  531. diag::err_asm_input_duplicate_match)
  532. << TiedTo;
  533. targetDiag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getBeginLoc(),
  534. diag::note_asm_input_duplicate_first)
  535. << TiedTo;
  536. return NS;
  537. }
  538. InputMatchedToOutput[TiedTo] = i;
  539. if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
  540. continue;
  541. QualType InTy = InputExpr->getType();
  542. QualType OutTy = OutputExpr->getType();
  543. if (Context.hasSameType(InTy, OutTy))
  544. continue; // All types can be tied to themselves.
  545. // Decide if the input and output are in the same domain (integer/ptr or
  546. // floating point.
  547. enum AsmDomain {
  548. AD_Int, AD_FP, AD_Other
  549. } InputDomain, OutputDomain;
  550. if (InTy->isIntegerType() || InTy->isPointerType())
  551. InputDomain = AD_Int;
  552. else if (InTy->isRealFloatingType())
  553. InputDomain = AD_FP;
  554. else
  555. InputDomain = AD_Other;
  556. if (OutTy->isIntegerType() || OutTy->isPointerType())
  557. OutputDomain = AD_Int;
  558. else if (OutTy->isRealFloatingType())
  559. OutputDomain = AD_FP;
  560. else
  561. OutputDomain = AD_Other;
  562. // They are ok if they are the same size and in the same domain. This
  563. // allows tying things like:
  564. // void* to int*
  565. // void* to int if they are the same size.
  566. // double to long double if they are the same size.
  567. //
  568. uint64_t OutSize = Context.getTypeSize(OutTy);
  569. uint64_t InSize = Context.getTypeSize(InTy);
  570. if (OutSize == InSize && InputDomain == OutputDomain &&
  571. InputDomain != AD_Other)
  572. continue;
  573. // If the smaller input/output operand is not mentioned in the asm string,
  574. // then we can promote the smaller one to a larger input and the asm string
  575. // won't notice.
  576. bool SmallerValueMentioned = false;
  577. // If this is a reference to the input and if the input was the smaller
  578. // one, then we have to reject this asm.
  579. if (isOperandMentioned(InputOpNo, Pieces)) {
  580. // This is a use in the asm string of the smaller operand. Since we
  581. // codegen this by promoting to a wider value, the asm will get printed
  582. // "wrong".
  583. SmallerValueMentioned |= InSize < OutSize;
  584. }
  585. if (isOperandMentioned(TiedTo, Pieces)) {
  586. // If this is a reference to the output, and if the output is the larger
  587. // value, then it's ok because we'll promote the input to the larger type.
  588. SmallerValueMentioned |= OutSize < InSize;
  589. }
  590. // If the smaller value wasn't mentioned in the asm string, and if the
  591. // output was a register, just extend the shorter one to the size of the
  592. // larger one.
  593. if (!SmallerValueMentioned && InputDomain != AD_Other &&
  594. OutputConstraintInfos[TiedTo].allowsRegister()) {
  595. // FIXME: GCC supports the OutSize to be 128 at maximum. Currently codegen
  596. // crash when the size larger than the register size. So we limit it here.
  597. if (OutTy->isStructureType() &&
  598. Context.getIntTypeForBitwidth(OutSize, /*Signed*/ false).isNull()) {
  599. targetDiag(OutputExpr->getExprLoc(), diag::err_store_value_to_reg);
  600. return NS;
  601. }
  602. continue;
  603. }
  604. // Either both of the operands were mentioned or the smaller one was
  605. // mentioned. One more special case that we'll allow: if the tied input is
  606. // integer, unmentioned, and is a constant, then we'll allow truncating it
  607. // down to the size of the destination.
  608. if (InputDomain == AD_Int && OutputDomain == AD_Int &&
  609. !isOperandMentioned(InputOpNo, Pieces) &&
  610. InputExpr->isEvaluatable(Context)) {
  611. CastKind castKind =
  612. (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
  613. InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
  614. Exprs[InputOpNo] = InputExpr;
  615. NS->setInputExpr(i, InputExpr);
  616. continue;
  617. }
  618. targetDiag(InputExpr->getBeginLoc(), diag::err_asm_tying_incompatible_types)
  619. << InTy << OutTy << OutputExpr->getSourceRange()
  620. << InputExpr->getSourceRange();
  621. return NS;
  622. }
  623. // Check for conflicts between clobber list and input or output lists
  624. SourceLocation ConstraintLoc =
  625. getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers,
  626. NumLabels,
  627. Context.getTargetInfo(), Context);
  628. if (ConstraintLoc.isValid())
  629. targetDiag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
  630. // Check for duplicate asm operand name between input, output and label lists.
  631. typedef std::pair<StringRef , Expr *> NamedOperand;
  632. SmallVector<NamedOperand, 4> NamedOperandList;
  633. for (unsigned i = 0, e = NumOutputs + NumInputs + NumLabels; i != e; ++i)
  634. if (Names[i])
  635. NamedOperandList.emplace_back(
  636. std::make_pair(Names[i]->getName(), Exprs[i]));
  637. // Sort NamedOperandList.
  638. llvm::stable_sort(NamedOperandList, llvm::less_first());
  639. // Find adjacent duplicate operand.
  640. SmallVector<NamedOperand, 4>::iterator Found =
  641. std::adjacent_find(begin(NamedOperandList), end(NamedOperandList),
  642. [](const NamedOperand &LHS, const NamedOperand &RHS) {
  643. return LHS.first == RHS.first;
  644. });
  645. if (Found != NamedOperandList.end()) {
  646. Diag((Found + 1)->second->getBeginLoc(),
  647. diag::error_duplicate_asm_operand_name)
  648. << (Found + 1)->first;
  649. Diag(Found->second->getBeginLoc(), diag::note_duplicate_asm_operand_name)
  650. << Found->first;
  651. return StmtError();
  652. }
  653. if (NS->isAsmGoto())
  654. setFunctionHasBranchIntoScope();
  655. CleanupVarDeclMarking();
  656. DiscardCleanupsInEvaluationContext();
  657. return NS;
  658. }
  659. void Sema::FillInlineAsmIdentifierInfo(Expr *Res,
  660. llvm::InlineAsmIdentifierInfo &Info) {
  661. QualType T = Res->getType();
  662. Expr::EvalResult Eval;
  663. if (T->isFunctionType() || T->isDependentType())
  664. return Info.setLabel(Res);
  665. if (Res->isPRValue()) {
  666. bool IsEnum = isa<clang::EnumType>(T);
  667. if (DeclRefExpr *DRE = dyn_cast<clang::DeclRefExpr>(Res))
  668. if (DRE->getDecl()->getKind() == Decl::EnumConstant)
  669. IsEnum = true;
  670. if (IsEnum && Res->EvaluateAsRValue(Eval, Context))
  671. return Info.setEnum(Eval.Val.getInt().getSExtValue());
  672. return Info.setLabel(Res);
  673. }
  674. unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
  675. unsigned Type = Size;
  676. if (const auto *ATy = Context.getAsArrayType(T))
  677. Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
  678. bool IsGlobalLV = false;
  679. if (Res->EvaluateAsLValue(Eval, Context))
  680. IsGlobalLV = Eval.isGlobalLValue();
  681. Info.setVar(Res, IsGlobalLV, Size, Type);
  682. }
  683. ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
  684. SourceLocation TemplateKWLoc,
  685. UnqualifiedId &Id,
  686. bool IsUnevaluatedContext) {
  687. if (IsUnevaluatedContext)
  688. PushExpressionEvaluationContext(
  689. ExpressionEvaluationContext::UnevaluatedAbstract,
  690. ReuseLambdaContextDecl);
  691. ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
  692. /*trailing lparen*/ false,
  693. /*is & operand*/ false,
  694. /*CorrectionCandidateCallback=*/nullptr,
  695. /*IsInlineAsmIdentifier=*/ true);
  696. if (IsUnevaluatedContext)
  697. PopExpressionEvaluationContext();
  698. if (!Result.isUsable()) return Result;
  699. Result = CheckPlaceholderExpr(Result.get());
  700. if (!Result.isUsable()) return Result;
  701. // Referring to parameters is not allowed in naked functions.
  702. if (CheckNakedParmReference(Result.get(), *this))
  703. return ExprError();
  704. QualType T = Result.get()->getType();
  705. if (T->isDependentType()) {
  706. return Result;
  707. }
  708. // Any sort of function type is fine.
  709. if (T->isFunctionType()) {
  710. return Result;
  711. }
  712. // Otherwise, it needs to be a complete type.
  713. if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
  714. return ExprError();
  715. }
  716. return Result;
  717. }
  718. bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
  719. unsigned &Offset, SourceLocation AsmLoc) {
  720. Offset = 0;
  721. SmallVector<StringRef, 2> Members;
  722. Member.split(Members, ".");
  723. NamedDecl *FoundDecl = nullptr;
  724. // MS InlineAsm uses 'this' as a base
  725. if (getLangOpts().CPlusPlus && Base.equals("this")) {
  726. if (const Type *PT = getCurrentThisType().getTypePtrOrNull())
  727. FoundDecl = PT->getPointeeType()->getAsTagDecl();
  728. } else {
  729. LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
  730. LookupOrdinaryName);
  731. if (LookupName(BaseResult, getCurScope()) && BaseResult.isSingleResult())
  732. FoundDecl = BaseResult.getFoundDecl();
  733. }
  734. if (!FoundDecl)
  735. return true;
  736. for (StringRef NextMember : Members) {
  737. const RecordType *RT = nullptr;
  738. if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
  739. RT = VD->getType()->getAs<RecordType>();
  740. else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
  741. MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
  742. // MS InlineAsm often uses struct pointer aliases as a base
  743. QualType QT = TD->getUnderlyingType();
  744. if (const auto *PT = QT->getAs<PointerType>())
  745. QT = PT->getPointeeType();
  746. RT = QT->getAs<RecordType>();
  747. } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
  748. RT = TD->getTypeForDecl()->getAs<RecordType>();
  749. else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
  750. RT = TD->getType()->getAs<RecordType>();
  751. if (!RT)
  752. return true;
  753. if (RequireCompleteType(AsmLoc, QualType(RT, 0),
  754. diag::err_asm_incomplete_type))
  755. return true;
  756. LookupResult FieldResult(*this, &Context.Idents.get(NextMember),
  757. SourceLocation(), LookupMemberName);
  758. if (!LookupQualifiedName(FieldResult, RT->getDecl()))
  759. return true;
  760. if (!FieldResult.isSingleResult())
  761. return true;
  762. FoundDecl = FieldResult.getFoundDecl();
  763. // FIXME: Handle IndirectFieldDecl?
  764. FieldDecl *FD = dyn_cast<FieldDecl>(FoundDecl);
  765. if (!FD)
  766. return true;
  767. const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
  768. unsigned i = FD->getFieldIndex();
  769. CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
  770. Offset += (unsigned)Result.getQuantity();
  771. }
  772. return false;
  773. }
  774. ExprResult
  775. Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
  776. SourceLocation AsmLoc) {
  777. QualType T = E->getType();
  778. if (T->isDependentType()) {
  779. DeclarationNameInfo NameInfo;
  780. NameInfo.setLoc(AsmLoc);
  781. NameInfo.setName(&Context.Idents.get(Member));
  782. return CXXDependentScopeMemberExpr::Create(
  783. Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(),
  784. SourceLocation(),
  785. /*FirstQualifierFoundInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr);
  786. }
  787. const RecordType *RT = T->getAs<RecordType>();
  788. // FIXME: Diagnose this as field access into a scalar type.
  789. if (!RT)
  790. return ExprResult();
  791. LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc,
  792. LookupMemberName);
  793. if (!LookupQualifiedName(FieldResult, RT->getDecl()))
  794. return ExprResult();
  795. // Only normal and indirect field results will work.
  796. ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
  797. if (!FD)
  798. FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl());
  799. if (!FD)
  800. return ExprResult();
  801. // Make an Expr to thread through OpDecl.
  802. ExprResult Result = BuildMemberReferenceExpr(
  803. E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
  804. SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
  805. return Result;
  806. }
  807. StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
  808. ArrayRef<Token> AsmToks,
  809. StringRef AsmString,
  810. unsigned NumOutputs, unsigned NumInputs,
  811. ArrayRef<StringRef> Constraints,
  812. ArrayRef<StringRef> Clobbers,
  813. ArrayRef<Expr*> Exprs,
  814. SourceLocation EndLoc) {
  815. bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
  816. setFunctionHasBranchProtectedScope();
  817. bool InvalidOperand = false;
  818. for (uint64_t I = 0; I < NumOutputs + NumInputs; ++I) {
  819. Expr *E = Exprs[I];
  820. if (E->getType()->isBitIntType()) {
  821. InvalidOperand = true;
  822. Diag(E->getBeginLoc(), diag::err_asm_invalid_type)
  823. << E->getType() << (I < NumOutputs)
  824. << E->getSourceRange();
  825. } else if (E->refersToBitField()) {
  826. InvalidOperand = true;
  827. FieldDecl *BitField = E->getSourceBitField();
  828. Diag(E->getBeginLoc(), diag::err_ms_asm_bitfield_unsupported)
  829. << E->getSourceRange();
  830. Diag(BitField->getLocation(), diag::note_bitfield_decl);
  831. }
  832. }
  833. if (InvalidOperand)
  834. return StmtError();
  835. MSAsmStmt *NS =
  836. new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
  837. /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
  838. Constraints, Exprs, AsmString,
  839. Clobbers, EndLoc);
  840. return NS;
  841. }
  842. LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
  843. SourceLocation Location,
  844. bool AlwaysCreate) {
  845. LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
  846. Location);
  847. if (Label->isMSAsmLabel()) {
  848. // If we have previously created this label implicitly, mark it as used.
  849. Label->markUsed(Context);
  850. } else {
  851. // Otherwise, insert it, but only resolve it if we have seen the label itself.
  852. std::string InternalName;
  853. llvm::raw_string_ostream OS(InternalName);
  854. // Create an internal name for the label. The name should not be a valid
  855. // mangled name, and should be unique. We use a dot to make the name an
  856. // invalid mangled name. We use LLVM's inline asm ${:uid} escape so that a
  857. // unique label is generated each time this blob is emitted, even after
  858. // inlining or LTO.
  859. OS << "__MSASMLABEL_.${:uid}__";
  860. for (char C : ExternalLabelName) {
  861. OS << C;
  862. // We escape '$' in asm strings by replacing it with "$$"
  863. if (C == '$')
  864. OS << '$';
  865. }
  866. Label->setMSAsmLabel(OS.str());
  867. }
  868. if (AlwaysCreate) {
  869. // The label might have been created implicitly from a previously encountered
  870. // goto statement. So, for both newly created and looked up labels, we mark
  871. // them as resolved.
  872. Label->setMSAsmLabelResolved();
  873. }
  874. // Adjust their location for being able to generate accurate diagnostics.
  875. Label->setLocation(Location);
  876. return Label;
  877. }