Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull Request- Syntax Plugin Infrastructure. #1

Merged
merged 5 commits into from
Aug 17, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions clang/examples/PrintTokensSyntax/PrintTokensSyntax.cpp
Original file line number Diff line number Diff line change
@@ -23,11 +23,17 @@ class PrintTokensHandler : public SyntaxHandler {
void GetReplacement(Preprocessor &PP, Declarator &D,
CachedTokens &Toks,
llvm::raw_string_ostream &OS) override {

OS << "static const char* tokens = \"";
for (auto &Tok : Toks) {
OS << "printf(\"%s\\n\", \"";
OS << " ";
OS.write_escaped(PP.getSpelling(Tok));
OS << "\");\n";
}
OS << "\";\n";
// Rewrite syntax original function.
OS << getDeclText(PP,D) << "{\n";
OS << "printf(\"%s\",tokens);\n";
OS <<"}\n";
}

void AddToPredefines(llvm::raw_string_ostream &OS) override {
3 changes: 2 additions & 1 deletion clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
@@ -3117,7 +3117,6 @@ class SyntaxHandler {
std::string Name;

virtual void anchor();

public:
SyntaxHandler() = default;
explicit SyntaxHandler(StringRef name) : Name(name) {}
@@ -3128,6 +3127,8 @@ class SyntaxHandler {
CachedTokens &Toks,
llvm::raw_string_ostream &OS) = 0;
virtual void AddToPredefines(llvm::raw_string_ostream &OS) = 0;
/// Utility function returns actual text of a declarator.
StringRef getDeclText(Preprocessor &PP,Declarator &D);
};

/// Registry of syntax handlers added by plugins
27 changes: 23 additions & 4 deletions clang/lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
@@ -25,7 +25,14 @@ using namespace clang;
LLVM_INSTANTIATE_REGISTRY(SyntaxHandlerRegistry)

void SyntaxHandler::anchor() {}

// Utility function returning actual text for a declarator.
llvm::StringRef SyntaxHandler::getDeclText(Preprocessor &PP,Declarator &D){
auto DeclCharRange = Lexer::getAsCharRange (D.getSourceRange(),
PP.getSourceManager(), PP.getLangOpts());
auto DeclText= Lexer::getSourceText (DeclCharRange,
PP.getSourceManager(), PP.getLangOpts());
return DeclText;
}
namespace {
/// A comment handler that passes comments found by the preprocessor
/// to the parser action.
@@ -1190,15 +1197,27 @@ void Parser::ProcessPluginSyntax(ParsingDeclarator &D) {
return;
}

// Provide the token stream to the plugin and get back the replacement text.

std::string Replacement;
llvm::raw_string_ostream ReplacementOS(Replacement);

ReplacementOS << "\n{\n";
SHI->second->GetReplacement(PP, D, Toks, ReplacementOS);
// Place __builtin_unreachable(); in the forgoten function. This
// is done to avoid warnings from the compiler.
ReplacementOS << "__builtin_unreachable();\n";
ReplacementOS << "\n}\n";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the function does not return void? Don't we get a warning that the function doesn't return an appropriate value?


// Provide the token stream to the plugin and get back the replacement text.
SHI->second->GetReplacement(PP, D, Toks, ReplacementOS);
ReplacementOS.flush();

// Change the identifier name in the declarator to forget
// the original function.

std::string NewName;
NewName ="__"+ D.getIdentifier()->getName().str();

IdentifierInfo &VariantII = Actions.Context.Idents.get(NewName);
D.SetIdentifier(&VariantII, D.getBeginLoc());

// Now we have a replacement text buffer from the plugin, enter it for
// lexing. After we're done with that, we'll resume parsing the original
43 changes: 22 additions & 21 deletions clang/test/Frontend/plugin-syntax-print-tokens.cpp
Original file line number Diff line number Diff line change
@@ -5,26 +5,27 @@
This is a test with a "string".
}

// CHECK: [[STR_VAR:@.+]] = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
// CHECK-NEXT: [[STR_VAR1:@.+]] = private unnamed_addr constant [5 x i8] c"This\00", align 1
// CHECK-NEXT: [[STR_VAR2:@.+]] = private unnamed_addr constant [3 x i8] c"is\00", align 1
// CHECK-NEXT: [[STR_VAR3:@.+]] = private unnamed_addr constant [2 x i8] c"a\00", align 1
// CHECK-NEXT: [[STR_VAR4:@.+]] = private unnamed_addr constant [5 x i8] c"test\00", align 1
// CHECK-NEXT: [[STR_VAR5:@.+]] = private unnamed_addr constant [5 x i8] c"with\00", align 1
// CHECK-NEXT: [[STR_VAR6:@.+]] = private unnamed_addr constant [9 x i8] c"\22string\22\00", align 1
// CHECK-NEXT: [[STR_VAR7:@.+]] = private unnamed_addr constant [2 x i8] c".\00", align 1

// CHECK: define dso_local void @_Z3fn1v() #0 {
// CHECK-NEXT: entry:
// CHECK-NEXT: %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[STR_VAR1]], {{.*}}))
// CHECK-NEXT: %call1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([3 x i8], [3 x i8]* [[STR_VAR2]], {{.*}}))
// CHECK-NEXT: %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([2 x i8], [2 x i8]* [[STR_VAR3]], {{.*}}))
// CHECK-NEXT: %call3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[STR_VAR4]], {{.*}}))
// CHECK-NEXT: %call4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[STR_VAR5]], {{.*}}))
// CHECK-NEXT: %call5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([2 x i8], [2 x i8]* [[STR_VAR3]], {{.*}}))
// CHECK-NEXT: %call6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([9 x i8], [9 x i8]* [[STR_VAR6]], {{.*}}))
// CHECK-NEXT: %call7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* [[STR_VAR]], {{.*}}), i8* getelementptr inbounds ([2 x i8], [2 x i8]* [[STR_VAR7]], {{.*}}))
// CHECK-NEXT: ret void
// CHECK-NEXT: }
//CHECK: [[STR_VAR:@.+]] = private unnamed_addr constant [3 x i8] c"%s\00", align 1
//CHECK-NEXT:@_ZL6tokens = internal global i8* getelementptr inbounds ([34 x i8], [34 x i8]* @.str.1, i32 0, i32 0), align 8
//CHECK-NEXT: [[STR_VAR:@.+]] = private unnamed_addr constant [34 x i8] c" This is a test with a \22string\22 .\00", align 1



//CHECK: define dso_local void @_Z5__fn1v() #0 {
//CHECK-NEXT: entry:
//CHECK-NEXT: unreachable
//CHECK-NEXT: }



//CHECK: define dso_local void @_Z3fn1v() #1 {
//CHECK-NEXT: entry:
//CHECK-NEXT: %0 = load i8*, i8** @_ZL6tokens, align 8
//CHECK-NEXT: %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i8* %0)
//CHECK-NEXT: ret void
//CHECK-NEXT: }