summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-08-19 10:33:04 +0000
committerdim <dim@FreeBSD.org>2012-08-19 10:33:04 +0000
commitcc73504950eb7b5dff2dded9bedd67bc36d64641 (patch)
tree5b9c2fa9d79942fbdce3d618e37e27c18263af9a /lib/Sema/SemaStmt.cpp
parent554bcb69c2d785a011a30e7db87a36a87fe7db10 (diff)
downloadFreeBSD-src-cc73504950eb7b5dff2dded9bedd67bc36d64641.zip
FreeBSD-src-cc73504950eb7b5dff2dded9bedd67bc36d64641.tar.gz
Vendor import of clang trunk r162107:
http://llvm.org/svn/llvm-project/cfe/trunk@162107
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r--lib/Sema/SemaStmt.cpp329
1 files changed, 221 insertions, 108 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index d22deb2..86884b7 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -28,6 +28,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -35,11 +36,15 @@
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
@@ -1516,7 +1521,6 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
StmtResult
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
- SourceLocation LParenLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc) {
@@ -1698,9 +1702,9 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
&& Collection->getType()->getAs<ObjCObjectPointerType>() != 0;
}
-/// ActOnCXXForRangeStmt - Check and build a C++0x for-range statement.
+/// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement.
///
-/// C++0x [stmt.ranged]:
+/// C++11 [stmt.ranged]:
/// A range-based for statement is equivalent to
///
/// {
@@ -1717,15 +1721,14 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
/// The body of the loop is not available yet, since it cannot be analysed until
/// we have determined the type of the for-range-declaration.
StmtResult
-Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
Stmt *First, SourceLocation ColonLoc, Expr *Range,
SourceLocation RParenLoc) {
if (!First || !Range)
return StmtError();
if (ObjCEnumerationCollection(Range))
- return ActOnObjCForCollectionStmt(ForLoc, LParenLoc, First, Range,
- RParenLoc);
+ return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc);
DeclStmt *DS = dyn_cast<DeclStmt>(First);
assert(DS && "first part of for range not a decl stmt");
@@ -2759,165 +2762,225 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return Owned(NS);
}
-// needSpaceAsmToken - This function handles whitespace around asm punctuation.
-// Returns true if a space should be emitted.
-static inline bool needSpaceAsmToken(Token currTok) {
- static Token prevTok;
-
- // No need for space after prevToken.
- switch(prevTok.getKind()) {
- default:
- break;
- case tok::l_square:
- case tok::r_square:
- case tok::l_brace:
- case tok::r_brace:
- case tok::colon:
- prevTok = currTok;
- return false;
- }
+// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. These
+// require special handling.
+static bool isMSAsmKeyword(StringRef Name) {
+ bool Ret = llvm::StringSwitch<bool>(Name)
+ .Cases("EVEN", "ALIGN", true) // Alignment directives.
+ .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes.
+ .Case("_emit", true) // _emit Pseudoinstruction.
+ .Default(false);
+ return Ret;
+}
- // No need for a space before currToken.
- switch(currTok.getKind()) {
- default:
- break;
- case tok::l_square:
- case tok::r_square:
- case tok::l_brace:
- case tok::r_brace:
- case tok::comma:
- case tok::colon:
- prevTok = currTok;
- return false;
- }
- prevTok = currTok;
- return true;
+static StringRef getSpelling(Sema &SemaRef, Token AsmTok) {
+ StringRef Asm;
+ SmallString<512> TokenBuf;
+ TokenBuf.resize(512);
+ bool StringInvalid = false;
+ Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid);
+ assert (!StringInvalid && "Expected valid string!");
+ return Asm;
}
static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple,
SourceLocation AsmLoc,
ArrayRef<Token> AsmToks,
- ArrayRef<unsigned> LineEnds,
const TargetInfo &TI,
+ std::vector<llvm::BitVector> &AsmRegs,
+ std::vector<llvm::BitVector> &AsmNames,
std::vector<std::string> &AsmStrings) {
assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
- // Assume simple asm stmt until we parse a non-register identifer.
+ // Assume simple asm stmt until we parse a non-register identifer (or we just
+ // need to bail gracefully).
IsSimple = true;
- for (unsigned i = 0, e = LineEnds.size(); i != e; ++i) {
- SmallString<512> Asm;
+ SmallString<512> Asm;
+ unsigned NumAsmStrings = 0;
+ for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) {
+
+ // Determine if this should be considered a new asm.
+ bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() ||
+ AsmToks[i].is(tok::kw_asm);
+
+ // Emit the previous asm string.
+ if (i && isNewAsm) {
+ AsmStrings[NumAsmStrings++] = Asm.c_str();
+ if (AsmToks[i].is(tok::kw_asm)) {
+ ++i; // Skip __asm
+ assert (i != e && "Expected another token.");
+ }
+ }
- // Check the operands.
- for (unsigned j = (i == 0) ? 0 : LineEnds[i-1], e = LineEnds[i]; j != e; ++j) {
+ // Start a new asm string with the opcode.
+ if (isNewAsm) {
+ AsmRegs[NumAsmStrings].resize(AsmToks.size());
+ AsmNames[NumAsmStrings].resize(AsmToks.size());
- IdentifierInfo *II;
- if (j == 0 || (i > 0 && j == LineEnds[i-1])) {
- II = AsmToks[j].getIdentifierInfo();
- Asm = II->getName().str();
- continue;
+ StringRef Piece = AsmToks[i].getIdentifierInfo()->getName();
+ // MS-style inline asm keywords require special handling.
+ if (isMSAsmKeyword(Piece))
+ IsSimple = false;
+
+ // TODO: Verify this is a valid opcode.
+ Asm = Piece;
+ continue;
+ }
+
+ if (i && AsmToks[i].hasLeadingSpace())
+ Asm += ' ';
+
+ // Check the operand(s).
+ switch (AsmToks[i].getKind()) {
+ default:
+ IsSimple = false;
+ Asm += getSpelling(SemaRef, AsmToks[i]);
+ break;
+ case tok::comma: Asm += ","; break;
+ case tok::colon: Asm += ":"; break;
+ case tok::l_square: Asm += "["; break;
+ case tok::r_square: Asm += "]"; break;
+ case tok::l_brace: Asm += "{"; break;
+ case tok::r_brace: Asm += "}"; break;
+ case tok::numeric_constant:
+ Asm += getSpelling(SemaRef, AsmToks[i]);
+ break;
+ case tok::identifier: {
+ IdentifierInfo *II = AsmToks[i].getIdentifierInfo();
+ StringRef Name = II->getName();
+
+ // Valid register?
+ if (TI.isValidGCCRegisterName(Name)) {
+ AsmRegs[NumAsmStrings].set(i);
+ Asm += Name;
+ break;
}
- if (needSpaceAsmToken(AsmToks[j]))
- Asm += " ";
+ IsSimple = false;
- switch (AsmToks[j].getKind()) {
- default:
- //llvm_unreachable("Unknown token.");
+ // MS-style inline asm keywords require special handling.
+ if (isMSAsmKeyword(Name)) {
+ IsSimple = false;
+ Asm += Name;
break;
- case tok::comma: Asm += ","; break;
- case tok::colon: Asm += ":"; break;
- case tok::l_square: Asm += "["; break;
- case tok::r_square: Asm += "]"; break;
- case tok::l_brace: Asm += "{"; break;
- case tok::r_brace: Asm += "}"; break;
- case tok::numeric_constant: {
- SmallString<32> TokenBuf;
- TokenBuf.resize(32);
- bool StringInvalid = false;
- Asm += SemaRef.PP.getSpelling(AsmToks[j], TokenBuf, &StringInvalid);
- assert (!StringInvalid && "Expected valid string!");
+ }
+
+ // FIXME: Why are we missing this segment register?
+ if (Name == "fs") {
+ Asm += Name;
break;
}
- case tok::identifier: {
- II = AsmToks[j].getIdentifierInfo();
- StringRef Name = II->getName();
- // Valid registers don't need modification.
- if (TI.isValidGCCRegisterName(Name)) {
- Asm += Name;
- break;
- }
+ // Lookup the identifier.
+ // TODO: Someone with more experience with clang should verify this the
+ // proper way of doing a symbol lookup.
+ DeclarationName DeclName(II);
+ Scope *CurScope = SemaRef.getCurScope();
+ LookupResult R(SemaRef, DeclName, AsmLoc, Sema::LookupOrdinaryName);
+ if (!SemaRef.LookupName(R, CurScope, false/*AllowBuiltinCreation*/))
+ break;
- // TODO: Lookup the identifier.
- IsSimple = false;
+ assert (R.isSingleResult() && "Expected a single result?!");
+ NamedDecl *Decl = R.getFoundDecl();
+ switch (Decl->getKind()) {
+ default:
+ assert(0 && "Unknown decl kind.");
+ break;
+ case Decl::Var: {
+ case Decl::ParmVar:
+ AsmNames[NumAsmStrings].set(i);
+
+ VarDecl *Var = cast<VarDecl>(Decl);
+ QualType Ty = Var->getType();
+ (void)Ty; // Avoid warning.
+ // TODO: Patch identifier with valid operand. One potential idea is to
+ // probe the backend with type information to guess the possible
+ // operand.
+ break;
+ }
}
- } // AsmToks[i].getKind()
+ break;
+ }
}
- AsmStrings[i] = Asm.c_str();
}
+
+ // Emit the final (and possibly only) asm string.
+ AsmStrings[NumAsmStrings] = Asm.c_str();
}
// Build the unmodified MSAsmString.
static std::string buildMSAsmString(Sema &SemaRef,
ArrayRef<Token> AsmToks,
- ArrayRef<unsigned> LineEnds) {
+ unsigned &NumAsmStrings) {
assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
+ NumAsmStrings = 0;
+
SmallString<512> Asm;
- SmallString<512> TokenBuf;
- TokenBuf.resize(512);
- unsigned AsmLineNum = 0;
for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
- const char *ThisTokBuf = &TokenBuf[0];
- bool StringInvalid = false;
- unsigned ThisTokLen =
- Lexer::getSpelling(AsmToks[i], ThisTokBuf, SemaRef.getSourceManager(),
- SemaRef.getLangOpts(), &StringInvalid);
- if (i && (!AsmLineNum || i != LineEnds[AsmLineNum-1]) &&
- needSpaceAsmToken(AsmToks[i]))
- Asm += ' ';
- Asm += StringRef(ThisTokBuf, ThisTokLen);
- if (i + 1 == LineEnds[AsmLineNum] && i + 1 != AsmToks.size()) {
- Asm += '\n';
- ++AsmLineNum;
+ bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() ||
+ AsmToks[i].is(tok::kw_asm);
+
+ if (isNewAsm) {
+ ++NumAsmStrings;
+ if (i)
+ Asm += '\n';
+ if (AsmToks[i].is(tok::kw_asm)) {
+ i++; // Skip __asm
+ assert (i != e && "Expected another token");
+ }
}
+
+ if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
+ Asm += ' ';
+
+ Asm += getSpelling(SemaRef, AsmToks[i]);
}
return Asm.c_str();
}
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
+ SourceLocation LBraceLoc,
ArrayRef<Token> AsmToks,
- ArrayRef<unsigned> LineEnds,
SourceLocation EndLoc) {
// MS-style inline assembly is not fully supported, so emit a warning.
Diag(AsmLoc, diag::warn_unsupported_msasm);
SmallVector<StringRef,4> Clobbers;
+ std::set<std::string> ClobberRegs;
+ SmallVector<IdentifierInfo*, 4> Inputs;
+ SmallVector<IdentifierInfo*, 4> Outputs;
// Empty asm statements don't need to instantiate the AsmParser, etc.
if (AsmToks.empty()) {
StringRef AsmString;
MSAsmStmt *NS =
- new (Context) MSAsmStmt(Context, AsmLoc, /* IsSimple */ true,
- /* IsVolatile */ true, AsmToks, LineEnds,
+ new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
+ /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
AsmString, Clobbers, EndLoc);
return Owned(NS);
}
- std::string AsmString = buildMSAsmString(*this, AsmToks, LineEnds);
+ unsigned NumAsmStrings;
+ std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings);
bool IsSimple;
+ std::vector<llvm::BitVector> Regs;
+ std::vector<llvm::BitVector> Names;
std::vector<std::string> PatchedAsmStrings;
- PatchedAsmStrings.resize(LineEnds.size());
+
+ Regs.resize(NumAsmStrings);
+ Names.resize(NumAsmStrings);
+ PatchedAsmStrings.resize(NumAsmStrings);
// Rewrite operands to appease the AsmParser.
- patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, LineEnds,
- Context.getTargetInfo(), PatchedAsmStrings);
+ patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks,
+ Context.getTargetInfo(), Regs, Names, PatchedAsmStrings);
// patchMSAsmStrings doesn't correctly patch non-simple asm statements.
if (!IsSimple) {
MSAsmStmt *NS =
- new (Context) MSAsmStmt(Context, AsmLoc, /* IsSimple */ true,
- /* IsVolatile */ true, AsmToks, LineEnds,
+ new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
+ /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
AsmString, Clobbers, EndLoc);
return Owned(NS);
}
@@ -2947,7 +3010,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
// Tell SrcMgr about this buffer, which is what the parser will pick up.
SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
- OwningPtr<llvm::MCStreamer> Str;
+ OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
OwningPtr<llvm::MCAsmParser>
Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
OwningPtr<llvm::MCTargetAsmParser>
@@ -2956,13 +3019,63 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
Parser->setAssemblerDialect(1);
Parser->setTargetParser(*TargetParser.get());
- // TODO: Start parsing.
+ // Prime the lexer.
+ Parser->Lex();
+
+ // Parse the opcode.
+ StringRef IDVal;
+ Parser->ParseIdentifier(IDVal);
+
+ // Canonicalize the opcode to lower case.
+ SmallString<128> Opcode;
+ for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
+ Opcode.push_back(tolower(IDVal[i]));
+
+ // Parse the operands.
+ llvm::SMLoc IDLoc;
+ SmallVector<llvm::MCParsedAsmOperand*, 8> Operands;
+ bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc,
+ Operands);
+ assert (!HadError && "Unexpected error parsing instruction");
+
+ // Match the MCInstr.
+ SmallVector<llvm::MCInst, 2> Instrs;
+ HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs);
+ assert (!HadError && "Unexpected error matching instruction");
+ assert ((Instrs.size() == 1) && "Expected only a single instruction.");
+
+ // Get the instruction descriptor.
+ llvm::MCInst Inst = Instrs[0];
+ const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
+ const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode());
+ llvm::MCInstPrinter *IP =
+ TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
+
+ // Build the list of clobbers.
+ for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) {
+ const llvm::MCOperand &Op = Inst.getOperand(i);
+ if (!Op.isReg())
+ continue;
+
+ std::string Reg;
+ llvm::raw_string_ostream OS(Reg);
+ IP->printRegName(OS, Op.getReg());
+
+ StringRef Clobber(OS.str());
+ if (!Context.getTargetInfo().isValidClobber(Clobber))
+ return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) <<
+ Clobber);
+ ClobberRegs.insert(Reg);
+ }
}
+ for (std::set<std::string>::iterator I = ClobberRegs.begin(),
+ E = ClobberRegs.end(); I != E; ++I)
+ Clobbers.push_back(*I);
MSAsmStmt *NS =
- new (Context) MSAsmStmt(Context, AsmLoc, IsSimple, /* IsVolatile */ true,
- AsmToks, LineEnds, AsmString, Clobbers, EndLoc);
-
+ new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
+ /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
+ AsmString, Clobbers, EndLoc);
return Owned(NS);
}
OpenPOWER on IntegriCloud