зеркало из https://github.com/microsoft/clang-1.git
PCH support for inline assembly statements.
This completes support for all of C (+ extensions). We can (again) build a PCH file for Carbon.h. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69385 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
409d4e716a
Коммит
cd7d5a9dc5
|
@ -1004,14 +1004,25 @@ public:
|
|||
Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
|
||||
StringLiteral **clobbers, SourceLocation rparenloc);
|
||||
|
||||
/// \brief Build an empty inline-assembly statement.
|
||||
explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty) { }
|
||||
|
||||
SourceLocation getAsmLoc() const { return AsmLoc; }
|
||||
void setAsmLoc(SourceLocation L) { AsmLoc = L; }
|
||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
||||
|
||||
bool isVolatile() const { return IsVolatile; }
|
||||
void setVolatile(bool V) { IsVolatile = V; }
|
||||
bool isSimple() const { return IsSimple; }
|
||||
void setSimple(bool V) { IsSimple = false; }
|
||||
|
||||
//===--- Asm String Analysis ---===//
|
||||
|
||||
const StringLiteral *getAsmString() const { return AsmStr; }
|
||||
StringLiteral *getAsmString() { return AsmStr; }
|
||||
|
||||
void setAsmString(StringLiteral *E) { AsmStr = E; }
|
||||
|
||||
/// AsmStringPiece - this is part of a decomposed asm string specification
|
||||
/// (for use with the AnalyzeAsmString function below). An asm string is
|
||||
/// considered to be a concatenation of these parts.
|
||||
|
@ -1125,7 +1136,13 @@ public:
|
|||
const Expr *getInputExpr(unsigned i) const {
|
||||
return const_cast<AsmStmt*>(this)->getInputExpr(i);
|
||||
}
|
||||
|
||||
|
||||
void setOutputsAndInputs(unsigned NumOutputs,
|
||||
unsigned NumInputs,
|
||||
const std::string *Names,
|
||||
StringLiteral **Constraints,
|
||||
Stmt **Exprs);
|
||||
|
||||
//===--- Other ---===//
|
||||
|
||||
/// getNamedOperand - Given a symbolic operand reference like %[foo],
|
||||
|
@ -1138,7 +1155,8 @@ public:
|
|||
unsigned getNumClobbers() const { return Clobbers.size(); }
|
||||
StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
|
||||
const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }
|
||||
|
||||
void setClobbers(StringLiteral **Clobbers, unsigned NumClobbers);
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(AsmLoc, RParenLoc);
|
||||
}
|
||||
|
|
|
@ -407,7 +407,8 @@ namespace clang {
|
|||
STMT_RETURN,
|
||||
/// \brief A DeclStmt record.
|
||||
STMT_DECL,
|
||||
/// FIXME: An AsmStmt record.
|
||||
/// \brief An AsmStmt record.
|
||||
STMT_ASM,
|
||||
/// \brief A PredefinedExpr record.
|
||||
EXPR_PREDEFINED,
|
||||
/// \brief A DeclRefExpr record.
|
||||
|
|
|
@ -129,8 +129,6 @@ private:
|
|||
void WriteIdentifierTable();
|
||||
void WriteAttributeRecord(const Attr *Attr);
|
||||
|
||||
void AddString(const std::string &Str, RecordData &Record);
|
||||
|
||||
public:
|
||||
/// \brief Create a new precompiled header writer that outputs to
|
||||
/// the given bitstream.
|
||||
|
@ -163,6 +161,9 @@ public:
|
|||
/// \brief Emit a declaration name.
|
||||
void AddDeclarationName(DeclarationName Name, RecordData &Record);
|
||||
|
||||
/// \brief Add a string to the given record.
|
||||
void AddString(const std::string &Str, RecordData &Record);
|
||||
|
||||
/// \brief Add the given statement or expression to the queue of statements to
|
||||
/// emit.
|
||||
///
|
||||
|
|
|
@ -175,6 +175,22 @@ std::string AsmStmt::getInputConstraint(unsigned i) const {
|
|||
}
|
||||
|
||||
|
||||
void AsmStmt::setOutputsAndInputs(unsigned NumOutputs,
|
||||
unsigned NumInputs,
|
||||
const std::string *Names,
|
||||
StringLiteral **Constraints,
|
||||
Stmt **Exprs) {
|
||||
this->NumOutputs = NumOutputs;
|
||||
this->NumInputs = NumInputs;
|
||||
this->Names.clear();
|
||||
this->Names.insert(this->Names.end(), Names, Names + NumOutputs + NumInputs);
|
||||
this->Constraints.clear();
|
||||
this->Constraints.insert(this->Constraints.end(),
|
||||
Constraints, Constraints + NumOutputs + NumInputs);
|
||||
this->Exprs.clear();
|
||||
this->Exprs.insert(this->Exprs.end(), Exprs, Exprs + NumOutputs + NumInputs);
|
||||
}
|
||||
|
||||
/// getNamedOperand - Given a symbolic operand reference like %[foo],
|
||||
/// translate this into a numeric value needed to reference the same operand.
|
||||
/// This returns -1 if the operand name is invalid.
|
||||
|
@ -195,6 +211,10 @@ int AsmStmt::getNamedOperand(const std::string &SymbolicName) const {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void AsmStmt::setClobbers(StringLiteral **Clobbers, unsigned NumClobbers) {
|
||||
this->Clobbers.clear();
|
||||
this->Clobbers.insert(this->Clobbers.end(), Clobbers, Clobbers + NumClobbers);
|
||||
}
|
||||
|
||||
/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
|
||||
/// it into pieces. If the asm string is erroneous, emit errors and return
|
||||
|
|
|
@ -262,6 +262,7 @@ namespace {
|
|||
unsigned VisitBreakStmt(BreakStmt *S);
|
||||
unsigned VisitReturnStmt(ReturnStmt *S);
|
||||
unsigned VisitDeclStmt(DeclStmt *S);
|
||||
unsigned VisitAsmStmt(AsmStmt *S);
|
||||
unsigned VisitExpr(Expr *E);
|
||||
unsigned VisitPredefinedExpr(PredefinedExpr *E);
|
||||
unsigned VisitDeclRefExpr(DeclRefExpr *E);
|
||||
|
@ -456,6 +457,42 @@ unsigned PCHStmtReader::VisitDeclStmt(DeclStmt *S) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitAsmStmt(AsmStmt *S) {
|
||||
VisitStmt(S);
|
||||
unsigned NumOutputs = Record[Idx++];
|
||||
unsigned NumInputs = Record[Idx++];
|
||||
unsigned NumClobbers = Record[Idx++];
|
||||
S->setAsmLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
S->setVolatile(Record[Idx++]);
|
||||
S->setSimple(Record[Idx++]);
|
||||
|
||||
unsigned StackIdx
|
||||
= StmtStack.size() - (NumOutputs*2 + NumInputs*2 + NumClobbers + 1);
|
||||
S->setAsmString(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
|
||||
|
||||
// Outputs and inputs
|
||||
llvm::SmallVector<std::string, 16> Names;
|
||||
llvm::SmallVector<StringLiteral*, 16> Constraints;
|
||||
llvm::SmallVector<Stmt*, 16> Exprs;
|
||||
for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
|
||||
Names.push_back(Reader.ReadString(Record, Idx));
|
||||
Constraints.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
|
||||
Exprs.push_back(StmtStack[StackIdx++]);
|
||||
}
|
||||
S->setOutputsAndInputs(NumOutputs, NumInputs,
|
||||
&Names[0], &Constraints[0], &Exprs[0]);
|
||||
|
||||
// Constraints
|
||||
llvm::SmallVector<StringLiteral*, 16> Clobbers;
|
||||
for (unsigned I = 0; I != NumClobbers; ++I)
|
||||
Clobbers.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++]));
|
||||
S->setClobbers(&Clobbers[0], NumClobbers);
|
||||
|
||||
assert(StackIdx == StmtStack.size() && "Error deserializing AsmStmt");
|
||||
return NumOutputs*2 + NumInputs*2 + NumClobbers + 1;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitExpr(Expr *E) {
|
||||
VisitStmt(E);
|
||||
E->setType(Reader.GetType(Record[Idx++]));
|
||||
|
@ -2273,6 +2310,10 @@ Stmt *PCHReader::ReadStmt() {
|
|||
S = new (Context) DeclStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_ASM:
|
||||
S = new (Context) AsmStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::EXPR_PREDEFINED:
|
||||
S = new (Context) PredefinedExpr(Empty);
|
||||
break;
|
||||
|
|
|
@ -463,6 +463,7 @@ namespace {
|
|||
void VisitBreakStmt(BreakStmt *S);
|
||||
void VisitReturnStmt(ReturnStmt *S);
|
||||
void VisitDeclStmt(DeclStmt *S);
|
||||
void VisitAsmStmt(AsmStmt *S);
|
||||
void VisitExpr(Expr *E);
|
||||
void VisitPredefinedExpr(PredefinedExpr *E);
|
||||
void VisitDeclRefExpr(DeclRefExpr *E);
|
||||
|
@ -640,6 +641,38 @@ void PCHStmtWriter::VisitDeclStmt(DeclStmt *S) {
|
|||
Code = pch::STMT_DECL;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) {
|
||||
VisitStmt(S);
|
||||
Record.push_back(S->getNumOutputs());
|
||||
Record.push_back(S->getNumInputs());
|
||||
Record.push_back(S->getNumClobbers());
|
||||
Writer.AddSourceLocation(S->getAsmLoc(), Record);
|
||||
Writer.AddSourceLocation(S->getRParenLoc(), Record);
|
||||
Record.push_back(S->isVolatile());
|
||||
Record.push_back(S->isSimple());
|
||||
Writer.WriteSubStmt(S->getAsmString());
|
||||
|
||||
// Outputs
|
||||
for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
|
||||
Writer.AddString(S->getOutputName(I), Record);
|
||||
Writer.WriteSubStmt(S->getOutputConstraintLiteral(I));
|
||||
Writer.WriteSubStmt(S->getOutputExpr(I));
|
||||
}
|
||||
|
||||
// Inputs
|
||||
for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) {
|
||||
Writer.AddString(S->getInputName(I), Record);
|
||||
Writer.WriteSubStmt(S->getInputConstraintLiteral(I));
|
||||
Writer.WriteSubStmt(S->getInputExpr(I));
|
||||
}
|
||||
|
||||
// Clobbers
|
||||
for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
|
||||
Writer.WriteSubStmt(S->getClobber(I));
|
||||
|
||||
Code = pch::STMT_ASM;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitExpr(Expr *E) {
|
||||
VisitStmt(E);
|
||||
Writer.AddTypeRef(E->getType(), Record);
|
||||
|
@ -1505,9 +1538,7 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
|
|||
Var->getStorageClass() == VarDecl::Static))
|
||||
ExternalDefinitions.push_back(ID);
|
||||
} else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) {
|
||||
if (Func->isThisDeclarationADefinition() &&
|
||||
Func->getStorageClass() != FunctionDecl::Static &&
|
||||
!Func->isInline())
|
||||
if (Func->isThisDeclarationADefinition())
|
||||
ExternalDefinitions.push_back(ID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Test this without pch.
|
||||
// RUN: clang-cc -include %S/asm.h -fsyntax-only -verify %s
|
||||
|
||||
// Test with pch.
|
||||
// RUN: clang-cc -emit-pch -o %t %S/asm.h &&
|
||||
// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s
|
||||
|
||||
|
||||
void call_f(void) { f(); }
|
||||
|
||||
void call_clobbers(void) { clobbers(); }
|
|
@ -0,0 +1,14 @@
|
|||
// Header for the PCH test asm.c
|
||||
|
||||
void f() {
|
||||
int i;
|
||||
|
||||
asm ("foo\n" : : "a" (i + 2));
|
||||
asm ("foo\n" : [symbolic_name] "=a" (i) : "[symbolic_name]" (i));
|
||||
}
|
||||
|
||||
void clobbers() {
|
||||
asm ("nop" : : : "ax", "#ax", "%ax");
|
||||
asm ("nop" : : : "eax", "rax", "ah", "al");
|
||||
asm ("nop" : : : "0", "%0", "#0");
|
||||
}
|
Загрузка…
Ссылка в новой задаче