diff options
author | Anders Carlsson <andersca@mac.com> | 2008-02-07 17:19:11 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2008-02-07 17:19:11 +0000 |
commit | 61900f0ef4fc705e62609939f30a375a9576e43d (patch) | |
tree | c3d572b8efb80268bb9418d182177396a9be9777 | |
parent | 419154d6d8e80ff2083dd039095781a0eb99444f (diff) |
Handle top-level asm declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46855 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/Decl.cpp | 7 | ||||
-rw-r--r-- | AST/DeclSerialization.cpp | 23 | ||||
-rw-r--r-- | CodeGen/ModuleBuilder.cpp | 9 | ||||
-rw-r--r-- | Driver/ASTConsumers.cpp | 6 | ||||
-rw-r--r-- | Parse/Parser.cpp | 22 | ||||
-rw-r--r-- | Sema/Sema.h | 3 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 7 | ||||
-rw-r--r-- | include/clang/AST/Decl.h | 23 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 4 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 2 |
10 files changed, 93 insertions, 13 deletions
diff --git a/AST/Decl.cpp b/AST/Decl.cpp index 78916c53b7..55abe6f34d 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -38,6 +38,7 @@ static unsigned nObjCCategoryImpl = 0; static unsigned nObjCCompatibleAlias = 0; static unsigned nObjCPropertyDecl = 0; static unsigned nLinkageSpecDecl = 0; +static unsigned nFileScopeAsmDecl = 0; static bool StatSwitch = false; @@ -169,7 +170,8 @@ void Decl::PrintStats() { nObjCCategoryImpl*sizeof(ObjCCategoryImplDecl)+ nObjCCompatibleAlias*sizeof(ObjCCompatibleAliasDecl)+ nObjCPropertyDecl*sizeof(ObjCPropertyDecl)+ - nLinkageSpecDecl*sizeof(LinkageSpecDecl))); + nLinkageSpecDecl*sizeof(LinkageSpecDecl)+ + nFileScopeAsmDecl*sizeof(FileScopeAsmDecl))); } @@ -240,6 +242,9 @@ void Decl::addDeclKind(const Kind k) { case LinkageSpec: nLinkageSpecDecl++; break; + case FileScopeAsm: + nFileScopeAsmDecl++; + break; } } diff --git a/AST/DeclSerialization.cpp b/AST/DeclSerialization.cpp index 146ebbacbe..cb91846a02 100644 --- a/AST/DeclSerialization.cpp +++ b/AST/DeclSerialization.cpp @@ -67,6 +67,9 @@ Decl* Decl::Create(Deserializer& D) { case Typedef: return TypedefDecl::CreateImpl(D); + + case FileScopeAsm: + return FileScopeAsmDecl::CreateImpl(D); } } @@ -438,3 +441,23 @@ void LinkageSpecDecl::ReadInRec(Deserializer& D) { Language = static_cast<LanguageIDs>(D.ReadInt()); D.ReadPtr(this->D); } + +//===----------------------------------------------------------------------===// +// FileScopeAsm Serialization. +//===----------------------------------------------------------------------===// + +void FileScopeAsmDecl::EmitImpl(llvm::Serializer& S) const +{ + Decl::EmitInRec(S); + S.EmitOwnedPtr(AsmString); +} + +FileScopeAsmDecl* FileScopeAsmDecl::CreateImpl(Deserializer& D) { + FileScopeAsmDecl* decl = new FileScopeAsmDecl(SourceLocation(), 0); + + decl->Decl::ReadInRec(D); + decl->AsmString = cast<StringLiteral>(D.ReadOwnedPtr<Expr>()); +// D.ReadOwnedPtr(D.ReadOwnedPtr<StringLiteral>())<#T * * Ptr#>, <#bool AutoRegister#>)(decl->AsmString); + + return decl; +} diff --git a/CodeGen/ModuleBuilder.cpp b/CodeGen/ModuleBuilder.cpp index 50d6fedadd..06467488a5 100644 --- a/CodeGen/ModuleBuilder.cpp +++ b/CodeGen/ModuleBuilder.cpp @@ -70,6 +70,15 @@ namespace { Builder->WarnUnsupported(LSD, "linkage spec"); // FIXME: implement C++ linkage, C linkage works mostly by C // language reuse already. + } else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) { + std::string AsmString(AD->getAsmString()->getStrData(), + AD->getAsmString()->getByteLength()); + + const std::string &S = Builder->getModule().getModuleInlineAsm(); + if (S.empty()) + Builder->getModule().setModuleInlineAsm(AsmString); + else + Builder->getModule().setModuleInlineAsm(S + '\n' + AsmString); } else { assert(isa<TypeDecl>(D) && "Unknown top level decl"); // TODO: handle debug info? diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 3868e7d75c..688619438b 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -97,6 +97,10 @@ void DeclPrinter:: PrintDecl(Decl *D) { Out << "Read top-level variable decl: '" << SD->getName() << "'\n"; } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { PrintLinkageSpec(LSD); + } else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) { + Out << "asm("; + AD->getAsmString()->printPretty(Out); + Out << ")\n"; } else { assert(0 && "Unknown decl type!"); } @@ -402,6 +406,8 @@ namespace { Out << "Read objc fwd protocol decl\n"; } else if (isa<ObjCClassDecl>(D)) { Out << "Read objc fwd class decl\n"; + } else if (isa<FileScopeAsmDecl>(D)) { + Out << "Read file scope asm decl\n"; } else { assert(0 && "Unknown decl type!"); } diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp index 6f2a71257a..32856fe82b 100644 --- a/Parse/Parser.cpp +++ b/Parse/Parser.cpp @@ -321,11 +321,7 @@ Parser::DeclTy *Parser::ParseExternalDeclaration() { return RV; } case tok::kw_asm: - ParseSimpleAsm(); - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - "top-level asm block"); - // TODO: Invoke action for top-level asm. - return 0; + return ParseSimpleAsm(); case tok::at: // @ is not a legal token unless objc is enabled, no need to check. return ParseObjCAtDirectives(); @@ -610,19 +606,25 @@ Parser::ExprResult Parser::ParseAsmStringLiteral() { /// [GNU] simple-asm-expr: /// 'asm' '(' asm-string-literal ')' /// -void Parser::ParseSimpleAsm() { +Parser::DeclTy *Parser::ParseSimpleAsm() { assert(Tok.is(tok::kw_asm) && "Not an asm!"); - ConsumeToken(); + SourceLocation Loc = ConsumeToken(); if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after, "asm"); - return; + return 0; } - SourceLocation Loc = ConsumeParen(); + ConsumeParen(); - ParseAsmStringLiteral(); + ExprResult Result = ParseAsmStringLiteral(); MatchRHSPunctuation(tok::r_paren, Loc); + + if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, + "top-level asm block")) + return 0; + + return Actions.ActOnFileScopeAsmDecl(Loc, Result.Val); } diff --git a/Sema/Sema.h b/Sema/Sema.h index 06a12e4f7f..f3595e1076 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -197,7 +197,8 @@ private: virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace, SourceLocation RBrace, const char *Lang, unsigned StrSize, DeclTy *D); - + virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprTy *expr); + /// Scope actions. virtual void ActOnPopScope(SourceLocation Loc, Scope *S); virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S); diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index cd546f3efc..00776912b0 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1711,6 +1711,13 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, Consumer.HandleTagDeclDefinition(Enum); } +Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, + ExprTy *expr) { + StringLiteral *AsmString = cast<StringLiteral>((Expr*)expr); + + return new FileScopeAsmDecl(Loc, AsmString); +} + Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace, SourceLocation RBrace, diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index cc96b0732d..07588e4c06 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -27,6 +27,7 @@ class Decl; namespace clang { class Expr; class Stmt; +class StringLiteral; class FunctionDecl; class IdentifierInfo; @@ -71,6 +72,7 @@ public: ObjCClass, ObjCForwardProtocol, LinkageSpec, + FileScopeAsm, // For each non-leaf class, we now define a mapping to the first/last member // of the class, to allow efficient classof. @@ -755,6 +757,27 @@ protected: friend Decl* Decl::Create(llvm::Deserializer& D); }; +class FileScopeAsmDecl : public Decl { + StringLiteral *AsmString; +public: + FileScopeAsmDecl(SourceLocation L, StringLiteral *asmstring) + : Decl(FileScopeAsm, L), AsmString(asmstring) {} + + const StringLiteral *getAsmString() const { return AsmString; } + StringLiteral *getAsmString() { return AsmString; } + static bool classof(const Decl *D) { + return D->getKind() == FileScopeAsm; + } + static bool classof(const FileScopeAsmDecl *D) { return true; } +protected: + /// EmitImpl - Serialize this FileScopeAsmDecl. Called by Decl::Emit. + virtual void EmitImpl(llvm::Serializer& S) const; + + /// CreateImpl - Deserialize a FileScopeAsmDecl. Called by Decl::Create. + static FileScopeAsmDecl* CreateImpl(llvm::Deserializer& D); + + friend Decl* Decl::Create(llvm::Deserializer& D); +}; /// LinkageSpecDecl - This represents a linkage specification. For example: /// extern "C" void foo(); diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 7a2081978d..003dd9e01b 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -141,6 +141,10 @@ public: return Decl; } + virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprTy *AsmString) { + return 0; + } + /// ActOnPopScope - This callback is called immediately before the specified /// scope is popped and deleted. virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {} diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 2712daa245..aae86549f0 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -256,7 +256,7 @@ private: DeclTy *ParseDeclarationOrFunctionDefinition(); DeclTy *ParseFunctionDefinition(Declarator &D); void ParseKNRParamDeclarations(Declarator &D); - void ParseSimpleAsm(); + DeclTy *ParseSimpleAsm(); ExprResult ParseAsmStringLiteral(); // Objective-C External Declarations |