SemaStmtAsm.cpp 37 KB

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