SemaStmtAsm.cpp revision cf81cd270e31f97bb88b51e24708e75cc604980e
1//===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===// 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 implements semantic analysis for inline asm statements. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Sema/SemaInternal.h" 15#include "clang/Sema/Scope.h" 16#include "clang/Sema/ScopeInfo.h" 17#include "clang/Sema/Initialization.h" 18#include "clang/Sema/Lookup.h" 19#include "clang/AST/TypeLoc.h" 20#include "clang/Lex/Preprocessor.h" 21#include "clang/Basic/TargetInfo.h" 22#include "llvm/ADT/ArrayRef.h" 23#include "llvm/ADT/BitVector.h" 24#include "llvm/ADT/SmallString.h" 25#include "llvm/MC/MCAsmInfo.h" 26#include "llvm/MC/MCContext.h" 27#include "llvm/MC/MCObjectFileInfo.h" 28#include "llvm/MC/MCRegisterInfo.h" 29#include "llvm/MC/MCStreamer.h" 30#include "llvm/MC/MCSubtargetInfo.h" 31#include "llvm/MC/MCTargetAsmParser.h" 32#include "llvm/MC/MCParser/MCAsmParser.h" 33#include "llvm/Support/SourceMgr.h" 34#include "llvm/Support/TargetRegistry.h" 35#include "llvm/Support/TargetSelect.h" 36using namespace clang; 37using namespace sema; 38 39/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently 40/// ignore "noop" casts in places where an lvalue is required by an inline asm. 41/// We emulate this behavior when -fheinous-gnu-extensions is specified, but 42/// provide a strong guidance to not use it. 43/// 44/// This method checks to see if the argument is an acceptable l-value and 45/// returns false if it is a case we can handle. 46static bool CheckAsmLValue(const Expr *E, Sema &S) { 47 // Type dependent expressions will be checked during instantiation. 48 if (E->isTypeDependent()) 49 return false; 50 51 if (E->isLValue()) 52 return false; // Cool, this is an lvalue. 53 54 // Okay, this is not an lvalue, but perhaps it is the result of a cast that we 55 // are supposed to allow. 56 const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); 57 if (E != E2 && E2->isLValue()) { 58 if (!S.getLangOpts().HeinousExtensions) 59 S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) 60 << E->getSourceRange(); 61 else 62 S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) 63 << E->getSourceRange(); 64 // Accept, even if we emitted an error diagnostic. 65 return false; 66 } 67 68 // None of the above, just randomly invalid non-lvalue. 69 return true; 70} 71 72/// isOperandMentioned - Return true if the specified operand # is mentioned 73/// anywhere in the decomposed asm string. 74static bool isOperandMentioned(unsigned OpNo, 75 ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) { 76 for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { 77 const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; 78 if (!Piece.isOperand()) continue; 79 80 // If this is a reference to the input and if the input was the smaller 81 // one, then we have to reject this asm. 82 if (Piece.getOperandNo() == OpNo) 83 return true; 84 } 85 return false; 86} 87 88StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, 89 bool IsVolatile, unsigned NumOutputs, 90 unsigned NumInputs, IdentifierInfo **Names, 91 MultiExprArg constraints, MultiExprArg exprs, 92 Expr *asmString, MultiExprArg clobbers, 93 SourceLocation RParenLoc) { 94 unsigned NumClobbers = clobbers.size(); 95 StringLiteral **Constraints = 96 reinterpret_cast<StringLiteral**>(constraints.data()); 97 Expr **Exprs = exprs.data(); 98 StringLiteral *AsmString = cast<StringLiteral>(asmString); 99 StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data()); 100 101 SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; 102 103 // The parser verifies that there is a string literal here. 104 if (!AsmString->isAscii()) 105 return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) 106 << AsmString->getSourceRange()); 107 108 for (unsigned i = 0; i != NumOutputs; i++) { 109 StringLiteral *Literal = Constraints[i]; 110 if (!Literal->isAscii()) 111 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 112 << Literal->getSourceRange()); 113 114 StringRef OutputName; 115 if (Names[i]) 116 OutputName = Names[i]->getName(); 117 118 TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); 119 if (!Context.getTargetInfo().validateOutputConstraint(Info)) 120 return StmtError(Diag(Literal->getLocStart(), 121 diag::err_asm_invalid_output_constraint) 122 << Info.getConstraintStr()); 123 124 // Check that the output exprs are valid lvalues. 125 Expr *OutputExpr = Exprs[i]; 126 if (CheckAsmLValue(OutputExpr, *this)) { 127 return StmtError(Diag(OutputExpr->getLocStart(), 128 diag::err_asm_invalid_lvalue_in_output) 129 << OutputExpr->getSourceRange()); 130 } 131 132 OutputConstraintInfos.push_back(Info); 133 } 134 135 SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; 136 137 for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { 138 StringLiteral *Literal = Constraints[i]; 139 if (!Literal->isAscii()) 140 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 141 << Literal->getSourceRange()); 142 143 StringRef InputName; 144 if (Names[i]) 145 InputName = Names[i]->getName(); 146 147 TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); 148 if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), 149 NumOutputs, Info)) { 150 return StmtError(Diag(Literal->getLocStart(), 151 diag::err_asm_invalid_input_constraint) 152 << Info.getConstraintStr()); 153 } 154 155 Expr *InputExpr = Exprs[i]; 156 157 // Only allow void types for memory constraints. 158 if (Info.allowsMemory() && !Info.allowsRegister()) { 159 if (CheckAsmLValue(InputExpr, *this)) 160 return StmtError(Diag(InputExpr->getLocStart(), 161 diag::err_asm_invalid_lvalue_in_input) 162 << Info.getConstraintStr() 163 << InputExpr->getSourceRange()); 164 } 165 166 if (Info.allowsRegister()) { 167 if (InputExpr->getType()->isVoidType()) { 168 return StmtError(Diag(InputExpr->getLocStart(), 169 diag::err_asm_invalid_type_in_input) 170 << InputExpr->getType() << Info.getConstraintStr() 171 << InputExpr->getSourceRange()); 172 } 173 } 174 175 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); 176 if (Result.isInvalid()) 177 return StmtError(); 178 179 Exprs[i] = Result.take(); 180 InputConstraintInfos.push_back(Info); 181 } 182 183 // Check that the clobbers are valid. 184 for (unsigned i = 0; i != NumClobbers; i++) { 185 StringLiteral *Literal = Clobbers[i]; 186 if (!Literal->isAscii()) 187 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 188 << Literal->getSourceRange()); 189 190 StringRef Clobber = Literal->getString(); 191 192 if (!Context.getTargetInfo().isValidClobber(Clobber)) 193 return StmtError(Diag(Literal->getLocStart(), 194 diag::err_asm_unknown_register_name) << Clobber); 195 } 196 197 GCCAsmStmt *NS = 198 new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, 199 NumInputs, Names, Constraints, Exprs, AsmString, 200 NumClobbers, Clobbers, RParenLoc); 201 // Validate the asm string, ensuring it makes sense given the operands we 202 // have. 203 SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces; 204 unsigned DiagOffs; 205 if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { 206 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) 207 << AsmString->getSourceRange(); 208 return StmtError(); 209 } 210 211 // Validate tied input operands for type mismatches. 212 for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { 213 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; 214 215 // If this is a tied constraint, verify that the output and input have 216 // either exactly the same type, or that they are int/ptr operands with the 217 // same size (int/long, int*/long, are ok etc). 218 if (!Info.hasTiedOperand()) continue; 219 220 unsigned TiedTo = Info.getTiedOperand(); 221 unsigned InputOpNo = i+NumOutputs; 222 Expr *OutputExpr = Exprs[TiedTo]; 223 Expr *InputExpr = Exprs[InputOpNo]; 224 225 if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) 226 continue; 227 228 QualType InTy = InputExpr->getType(); 229 QualType OutTy = OutputExpr->getType(); 230 if (Context.hasSameType(InTy, OutTy)) 231 continue; // All types can be tied to themselves. 232 233 // Decide if the input and output are in the same domain (integer/ptr or 234 // floating point. 235 enum AsmDomain { 236 AD_Int, AD_FP, AD_Other 237 } InputDomain, OutputDomain; 238 239 if (InTy->isIntegerType() || InTy->isPointerType()) 240 InputDomain = AD_Int; 241 else if (InTy->isRealFloatingType()) 242 InputDomain = AD_FP; 243 else 244 InputDomain = AD_Other; 245 246 if (OutTy->isIntegerType() || OutTy->isPointerType()) 247 OutputDomain = AD_Int; 248 else if (OutTy->isRealFloatingType()) 249 OutputDomain = AD_FP; 250 else 251 OutputDomain = AD_Other; 252 253 // They are ok if they are the same size and in the same domain. This 254 // allows tying things like: 255 // void* to int* 256 // void* to int if they are the same size. 257 // double to long double if they are the same size. 258 // 259 uint64_t OutSize = Context.getTypeSize(OutTy); 260 uint64_t InSize = Context.getTypeSize(InTy); 261 if (OutSize == InSize && InputDomain == OutputDomain && 262 InputDomain != AD_Other) 263 continue; 264 265 // If the smaller input/output operand is not mentioned in the asm string, 266 // then we can promote the smaller one to a larger input and the asm string 267 // won't notice. 268 bool SmallerValueMentioned = false; 269 270 // If this is a reference to the input and if the input was the smaller 271 // one, then we have to reject this asm. 272 if (isOperandMentioned(InputOpNo, Pieces)) { 273 // This is a use in the asm string of the smaller operand. Since we 274 // codegen this by promoting to a wider value, the asm will get printed 275 // "wrong". 276 SmallerValueMentioned |= InSize < OutSize; 277 } 278 if (isOperandMentioned(TiedTo, Pieces)) { 279 // If this is a reference to the output, and if the output is the larger 280 // value, then it's ok because we'll promote the input to the larger type. 281 SmallerValueMentioned |= OutSize < InSize; 282 } 283 284 // If the smaller value wasn't mentioned in the asm string, and if the 285 // output was a register, just extend the shorter one to the size of the 286 // larger one. 287 if (!SmallerValueMentioned && InputDomain != AD_Other && 288 OutputConstraintInfos[TiedTo].allowsRegister()) 289 continue; 290 291 // Either both of the operands were mentioned or the smaller one was 292 // mentioned. One more special case that we'll allow: if the tied input is 293 // integer, unmentioned, and is a constant, then we'll allow truncating it 294 // down to the size of the destination. 295 if (InputDomain == AD_Int && OutputDomain == AD_Int && 296 !isOperandMentioned(InputOpNo, Pieces) && 297 InputExpr->isEvaluatable(Context)) { 298 CastKind castKind = 299 (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); 300 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); 301 Exprs[InputOpNo] = InputExpr; 302 NS->setInputExpr(i, InputExpr); 303 continue; 304 } 305 306 Diag(InputExpr->getLocStart(), 307 diag::err_asm_tying_incompatible_types) 308 << InTy << OutTy << OutputExpr->getSourceRange() 309 << InputExpr->getSourceRange(); 310 return StmtError(); 311 } 312 313 return Owned(NS); 314} 315 316// getSpelling - Get the spelling of the AsmTok token. 317static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { 318 StringRef Asm; 319 SmallString<512> TokenBuf; 320 TokenBuf.resize(512); 321 bool StringInvalid = false; 322 Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); 323 assert (!StringInvalid && "Expected valid string!"); 324 return Asm; 325} 326 327// Build the inline assembly string. Returns true on error. 328static bool buildMSAsmString(Sema &SemaRef, 329 SourceLocation AsmLoc, 330 ArrayRef<Token> AsmToks, 331 std::string &AsmString) { 332 assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); 333 334 SmallString<512> Asm; 335 for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { 336 bool isNewAsm = ((i == 0) || 337 AsmToks[i].isAtStartOfLine() || 338 AsmToks[i].is(tok::kw_asm)); 339 if (isNewAsm) { 340 if (i != 0) 341 Asm += "\n\t"; 342 343 if (AsmToks[i].is(tok::kw_asm)) { 344 i++; // Skip __asm 345 if (i == e) { 346 SemaRef.Diag(AsmLoc, diag::err_asm_empty); 347 return true; 348 } 349 350 } 351 } 352 353 if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) 354 Asm += ' '; 355 356 StringRef Spelling = getSpelling(SemaRef, AsmToks[i]); 357 Asm += Spelling; 358 } 359 AsmString = Asm.str(); 360 return false; 361} 362 363class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback { 364 Sema *SemaRef; 365 366public: 367 MCAsmParserSemaCallbackImpl(class Sema *Ref) { SemaRef = Ref; } 368 ~MCAsmParserSemaCallbackImpl() {} 369 370 void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){ 371 SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); 372 NamedDecl *OpDecl = SemaRef->LookupInlineAsmIdentifier(Name, Loc, Size); 373 return static_cast<void *>(OpDecl); 374 } 375}; 376 377NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, 378 unsigned &Size) { 379 Size = 0; 380 LookupResult Result(*this, &Context.Idents.get(Name), Loc, 381 Sema::LookupOrdinaryName); 382 383 if (!LookupName(Result, getCurScope())) { 384 // If we don't find anything, return null; the AsmParser will assume 385 // it is a label of some sort. 386 return 0; 387 } 388 389 if (!Result.isSingleResult()) { 390 // FIXME: Diagnose result. 391 return 0; 392 } 393 394 NamedDecl *ND = Result.getFoundDecl(); 395 if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { 396 if (VarDecl *Var = dyn_cast<VarDecl>(ND)) 397 Size = Context.getTypeInfo(Var->getType()).first; 398 399 return ND; 400 } 401 402 // FIXME: Handle other kinds of results? (FieldDecl, etc.) 403 // FIXME: Diagnose if we find something we can't handle, like a typedef. 404 return 0; 405} 406 407StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, 408 ArrayRef<Token> AsmToks,SourceLocation EndLoc) { 409 SmallVector<IdentifierInfo*, 4> Names; 410 SmallVector<StringRef, 4> ConstraintRefs; 411 SmallVector<Expr*, 4> Exprs; 412 SmallVector<StringRef, 4> ClobberRefs; 413 414 // Empty asm statements don't need to instantiate the AsmParser, etc. 415 if (AsmToks.empty()) { 416 StringRef EmptyAsmStr; 417 MSAsmStmt *NS = 418 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, 419 /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0, 420 /*NumInputs*/ 0, Names, ConstraintRefs, Exprs, 421 EmptyAsmStr, ClobberRefs, EndLoc); 422 return Owned(NS); 423 } 424 425 std::string AsmString; 426 if (buildMSAsmString(*this, AsmLoc, AsmToks, AsmString)) 427 return StmtError(); 428 429 // Get the target specific parser. 430 std::string Error; 431 const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); 432 const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); 433 434 OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); 435 OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); 436 OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); 437 OwningPtr<llvm::MCSubtargetInfo> 438 STI(TheTarget->createMCSubtargetInfo(TT, "", "")); 439 440 llvm::SourceMgr SrcMgr; 441 llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); 442 llvm::MemoryBuffer *Buffer = 443 llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>"); 444 445 // Tell SrcMgr about this buffer, which is what the parser will pick up. 446 SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); 447 448 OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); 449 OwningPtr<llvm::MCAsmParser> 450 Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); 451 OwningPtr<llvm::MCTargetAsmParser> 452 TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); 453 454 // Get the instruction descriptor. 455 const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); 456 llvm::MCInstPrinter *IP = 457 TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); 458 459 // Change to the Intel dialect. 460 Parser->setAssemblerDialect(1); 461 Parser->setTargetParser(*TargetParser.get()); 462 Parser->setParsingInlineAsm(true); 463 TargetParser->setParsingInlineAsm(true); 464 465 unsigned NumOutputs; 466 unsigned NumInputs; 467 std::string AsmStringIR; 468 SmallVector<void *, 4> OpDecls; 469 SmallVector<std::string, 4> Constraints; 470 SmallVector<std::string, 4> Clobbers; 471 MCAsmParserSemaCallbackImpl MCAPSI(this); 472 if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, 473 NumOutputs, NumInputs, OpDecls, Constraints, 474 Clobbers, MII, IP, MCAPSI)) 475 return StmtError(); 476 477 // Build the vector of clobber StringRefs. 478 unsigned NumClobbers = Clobbers.size(); 479 ClobberRefs.resize(NumClobbers); 480 for (unsigned i = 0; i != NumClobbers; ++i) 481 ClobberRefs[i] = StringRef(Clobbers[i]); 482 483 // Recast the void pointers and build the vector of constraint StringRefs. 484 unsigned NumExprs = NumOutputs + NumInputs; 485 Names.resize(NumExprs); 486 ConstraintRefs.resize(NumExprs); 487 Exprs.resize(NumExprs); 488 for (unsigned i = 0, e = NumExprs; i != e; ++i) { 489 NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i]); 490 if (!OpDecl) 491 return StmtError(); 492 493 DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc); 494 ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, 495 OpDecl); 496 if (OpExpr.isInvalid()) 497 return StmtError(); 498 499 Names[i] = OpDecl->getIdentifier(); 500 ConstraintRefs[i] = StringRef(Constraints[i]); 501 Exprs[i] = OpExpr.take(); 502 } 503 504 bool IsSimple = NumExprs > 0; 505 MSAsmStmt *NS = 506 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, 507 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs, 508 Names, ConstraintRefs, Exprs, AsmStringIR, 509 ClobberRefs, EndLoc); 510 return Owned(NS); 511} 512