Intrinsic/Custom Function Creation with Pragmas

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Intrinsic/Custom Function Creation with Pragmas

Prakash Prabhu
Hi,

I would like to define some custom pragmas of the following kind, where one can associate abstract locks with functions/structured code blocks using annotations:

Abstract Locks at the function interface level:
#pragma AbstractLock L1
void foo();

Abstract Locks for anonymous code blocks:
#pragma AbstractLock L2
{
  int tmp;
  tmp = a;
  a = tmp + 1;
}

Abstract locks could even be parameterized and depend additionally on variables live at point of specification/function parameters:

// L1 is parameterized by param1 and param2
#pragma AbstractLock L1 param1 param2
void foo(int param1, int param2, int param3);

// L1 is parameterized by x
int x;
x= ...
#pragma AbstractLock L2 x
{
  int tmp;
  tmp = a;
  a = tmp + 1;
}

I would like to use clang to pre-process these pragmas, create some kind of annotation structure in the emitted bit code, for use in the llvm backend (in one of the opt passes). I was thinking of creating an LLVM intrinsic/Set of Custom function calls to represent the abstract lock information in the bit code -- the functions by themselves do not exist and the only purpose of these calls is to give info to the backend about abstract locks. I looked at the llvm.annotation intrinsic, but since it uses a global string, I thought references to variable names (inside the global string) etc may not remain consistent in wake of front-end refactoring/optimizations. My current plan is to:

Create a custom Pragma Handler, say, PragmaAbstractLockHandler, that parses the AbstractLock pragma, and depending on whether the annotation is at the interface level or inside client code, create calls to the following functions:

-- For annotations at interface level, insert a call to the following function into a global section:
void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question.

-- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables

void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope

The above functions would be immediately processed in the backend as the first pass of opt (by creating appropriate data structures in the backend) and calls will be removed from the bit code -- after creating nonymous functions for the sections of code marked by abstract locks etc..

I would greatly appreciate any suggestions on how to go about translating the pragmas to the above functions in clang, or if there might be a better way to achieve the same with other front-end constructs, that will be great. How do I create a HandlePragma method that Lexes till the end of the code section/function declaration, create an Action that adds these functions in source code ? 

Thanks for your time.

- Prakash


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Intrinsic/Custom Function Creation with Pragmas

Douglas Gregor

On Jan 4, 2010, at 2:37 PM, Prakash Prabhu wrote:

> Hi,
>
> I would like to define some custom pragmas of the following kind, where one can associate abstract locks with functions/structured code blocks using annotations:
>
> Abstract Locks at the function interface level:
> #pragma AbstractLock L1
> void foo();
>
> Abstract Locks for anonymous code blocks:
> #pragma AbstractLock L2
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> Abstract locks could even be parameterized and depend additionally on variables live at point of specification/function parameters:
>
> // L1 is parameterized by param1 and param2
> #pragma AbstractLock L1 param1 param2
> void foo(int param1, int param2, int param3);

It might be easier to implement this as a new attribute on functions, since attributes are automatically associated with declarations or types. Then, you can avoid the problem of teaching a #pragma that comes *before* a declaration to associate itself with the correct declaration.

It might look something like:

        void __attribute__((lock(L1, param1, param2))) foo(int param1, int param2, int param3);

> // L1 is parameterized by x
> int x;
> x= ...
> #pragma AbstractLock L2 x
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> I would like to use clang to pre-process these pragmas, create some kind of annotation structure in the emitted bit code, for use in the llvm backend (in one of the opt passes). I was thinking of creating an LLVM intrinsic/Set of Custom function calls to represent the abstract lock information in the bit code -- the functions by themselves do not exist and the only purpose of these calls is to give info to the backend about abstract locks. I looked at the llvm.annotation intrinsic, but since it uses a global string, I thought references to variable names (inside the global string) etc may not remain consistent in wake of front-end refactoring/optimizations. My current plan is to:
>
> Create a custom Pragma Handler, say, PragmaAbstractLockHandler, that parses the AbstractLock pragma, and depending on whether the annotation is at the interface level or inside client code, create calls to the following functions:
>
> -- For annotations at interface level, insert a call to the following function into a global section:
> void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question.

> -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
> void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables
>
> void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope
>
> The above functions would be immediately processed in the backend as the first pass of opt (by creating appropriate data structures in the backend) and calls will be removed from the bit code -- after creating nonymous functions for the sections of code marked by abstract locks etc..

This makes perfect sense.

> I would greatly appreciate any suggestions on how to go about translating the pragmas to the above functions in clang, or if there might be a better way to achieve the same with other front-end constructs, that will be great. How do I create a HandlePragma method that Lexes till the end of the code section/function declaration, create an Action that adds these functions in source code ?


There's really no way to create a HandlePragma method that lexes until the end of the code section. Typically, what we do is have HandlePragma set some state in the Sema object that indicates the presence of your particular pragma. Then, when Clang parses the corresponding construct (say, a compound statement), the semantic analysis for that compound statement will check whether a #pragma was parsed and perform the appropriate transformations.

        - Doug
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Intrinsic/Custom Function Creation with Pragmas

Prakash Prabhu
Hi Doug,

Thanks a lot for your reply. I was able to add the #pragma, parse it successfully, determine the functions/compound statements to which they are attached by adding code to Sema's ActOnCompoundStmt() and a new function called from ParseFunctionDeclarator(). For the pragmas associated with the function interface, I am able to generate calls in a global function inside the LLVM bit code (by changing CodeGenModule.cpp) to:

" void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question. "

Multiple pragma's attached to a single block also seem to work (with the help of a pragma stack).

Although some of the above places may not be the best (in terms of their actual semantics and diagnostics/error checking which I may need at some point in the future), right now it gets the job done.

Now, I am at point where I would like to add calls in the LLVM bit code for compound statements. After looking around in the code for a while,  I still do not have a straightforward solution on how to go about generating calls for compound statments as mentioned in my previous mail:

" -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables

void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope "

The main issue is how to generate the Value* passed in as parameters to __AbstractLockInfoAtClientSiteBegin(), after validating that the variables specified in the #pragma:

// L1 is parameterized by x
int x;
x= ...
#pragma AbstractLock L2 x
{
  int tmp;
  tmp = a;
  a = tmp + 1;
}

In the above code, I would like to verify that x is declared and is in scope before I generate a Value* for it in the AbstractLock...Begin function call. I was thinking of the following possibility: In Semantic Actions phase (ActOnCompoundStmt() to be more specific), verify that x is in scope and generate CallExpr before and after the Compound Stmt, wrap this whole triple into a Compound statment and return it. To do this: (a) How do I get access to the variable declaration of 'x' from this point (ActOnCompoundStmt) -- is there a way to walk up the scope tree/AST and at each point look for a declaration of x in some kind of symbol table/declaration structure ? (b) Is there a easy way to create two AST nodes having CallExpr's  to functions that do not have a declaration yet (maybe I need to create the declarations?).

Alternatively, if there is way to verify the scope and find the type of the variables used (given just the identifier name), at the code generation time, that would be great too. 

Thanks, again, for your time!

regards,
Prakash

On Tue, Jan 5, 2010 at 11:15 AM, Douglas Gregor <[hidden email]> wrote:

On Jan 4, 2010, at 2:37 PM, Prakash Prabhu wrote:

> Hi,
>
> I would like to define some custom pragmas of the following kind, where one can associate abstract locks with functions/structured code blocks using annotations:
>
> Abstract Locks at the function interface level:
> #pragma AbstractLock L1
> void foo();
>
> Abstract Locks for anonymous code blocks:
> #pragma AbstractLock L2
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> Abstract locks could even be parameterized and depend additionally on variables live at point of specification/function parameters:
>
> // L1 is parameterized by param1 and param2
> #pragma AbstractLock L1 param1 param2
> void foo(int param1, int param2, int param3);

It might be easier to implement this as a new attribute on functions, since attributes are automatically associated with declarations or types. Then, you can avoid the problem of teaching a #pragma that comes *before* a declaration to associate itself with the correct declaration.

It might look something like:

       void __attribute__((lock(L1, param1, param2))) foo(int param1, int param2, int param3);

> // L1 is parameterized by x
> int x;
> x= ...
> #pragma AbstractLock L2 x
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> I would like to use clang to pre-process these pragmas, create some kind of annotation structure in the emitted bit code, for use in the llvm backend (in one of the opt passes). I was thinking of creating an LLVM intrinsic/Set of Custom function calls to represent the abstract lock information in the bit code -- the functions by themselves do not exist and the only purpose of these calls is to give info to the backend about abstract locks. I looked at the llvm.annotation intrinsic, but since it uses a global string, I thought references to variable names (inside the global string) etc may not remain consistent in wake of front-end refactoring/optimizations. My current plan is to:
>
> Create a custom Pragma Handler, say, PragmaAbstractLockHandler, that parses the AbstractLock pragma, and depending on whether the annotation is at the interface level or inside client code, create calls to the following functions:
>
> -- For annotations at interface level, insert a call to the following function into a global section:
> void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question.

> -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
> void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables
>
> void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope
>
> The above functions would be immediately processed in the backend as the first pass of opt (by creating appropriate data structures in the backend) and calls will be removed from the bit code -- after creating nonymous functions for the sections of code marked by abstract locks etc..

This makes perfect sense.

> I would greatly appreciate any suggestions on how to go about translating the pragmas to the above functions in clang, or if there might be a better way to achieve the same with other front-end constructs, that will be great. How do I create a HandlePragma method that Lexes till the end of the code section/function declaration, create an Action that adds these functions in source code ?


There's really no way to create a HandlePragma method that lexes until the end of the code section. Typically, what we do is have HandlePragma set some state in the Sema object that indicates the presence of your particular pragma. Then, when Clang parses the corresponding construct (say, a compound statement), the semantic analysis for that compound statement will check whether a #pragma was parsed and perform the appropriate transformations.

       - Doug


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Intrinsic/Custom Function Creation with Pragmas

Prakash Prabhu
Hi Doug,

Never mind about the earlier mail. I looked up Lookup.h (!) and was able to code in identifier resolution without much hassle and also the creation of CallExpr's with appropriate calls to the variadic functions. clang really is easy-to-use/modify ... thanks!

- Prakash


On Fri, Jan 8, 2010 at 10:25 PM, Prakash Prabhu <[hidden email]> wrote:
Hi Doug,

Thanks a lot for your reply. I was able to add the #pragma, parse it successfully, determine the functions/compound statements to which they are attached by adding code to Sema's ActOnCompoundStmt() and a new function called from ParseFunctionDeclarator(). For the pragmas associated with the function interface, I am able to generate calls in a global function inside the LLVM bit code (by changing CodeGenModule.cpp) to:

" void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question. "

Multiple pragma's attached to a single block also seem to work (with the help of a pragma stack).

Although some of the above places may not be the best (in terms of their actual semantics and diagnostics/error checking which I may need at some point in the future), right now it gets the job done.

Now, I am at point where I would like to add calls in the LLVM bit code for compound statements. After looking around in the code for a while,  I still do not have a straightforward solution on how to go about generating calls for compound statments as mentioned in my previous mail:

" -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables

void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope "

The main issue is how to generate the Value* passed in as parameters to __AbstractLockInfoAtClientSiteBegin(), after validating that the variables specified in the #pragma:

// L1 is parameterized by x
int x;
x= ...
#pragma AbstractLock L2 x
{
  int tmp;
  tmp = a;
  a = tmp + 1;
}

In the above code, I would like to verify that x is declared and is in scope before I generate a Value* for it in the AbstractLock...Begin function call. I was thinking of the following possibility: In Semantic Actions phase (ActOnCompoundStmt() to be more specific), verify that x is in scope and generate CallExpr before and after the Compound Stmt, wrap this whole triple into a Compound statment and return it. To do this: (a) How do I get access to the variable declaration of 'x' from this point (ActOnCompoundStmt) -- is there a way to walk up the scope tree/AST and at each point look for a declaration of x in some kind of symbol table/declaration structure ? (b) Is there a easy way to create two AST nodes having CallExpr's  to functions that do not have a declaration yet (maybe I need to create the declarations?).

Alternatively, if there is way to verify the scope and find the type of the variables used (given just the identifier name), at the code generation time, that would be great too. 

Thanks, again, for your time!

regards,
Prakash

On Tue, Jan 5, 2010 at 11:15 AM, Douglas Gregor <[hidden email]> wrote:

On Jan 4, 2010, at 2:37 PM, Prakash Prabhu wrote:

> Hi,
>
> I would like to define some custom pragmas of the following kind, where one can associate abstract locks with functions/structured code blocks using annotations:
>
> Abstract Locks at the function interface level:
> #pragma AbstractLock L1
> void foo();
>
> Abstract Locks for anonymous code blocks:
> #pragma AbstractLock L2
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> Abstract locks could even be parameterized and depend additionally on variables live at point of specification/function parameters:
>
> // L1 is parameterized by param1 and param2
> #pragma AbstractLock L1 param1 param2
> void foo(int param1, int param2, int param3);

It might be easier to implement this as a new attribute on functions, since attributes are automatically associated with declarations or types. Then, you can avoid the problem of teaching a #pragma that comes *before* a declaration to associate itself with the correct declaration.

It might look something like:

       void __attribute__((lock(L1, param1, param2))) foo(int param1, int param2, int param3);

> // L1 is parameterized by x
> int x;
> x= ...
> #pragma AbstractLock L2 x
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> I would like to use clang to pre-process these pragmas, create some kind of annotation structure in the emitted bit code, for use in the llvm backend (in one of the opt passes). I was thinking of creating an LLVM intrinsic/Set of Custom function calls to represent the abstract lock information in the bit code -- the functions by themselves do not exist and the only purpose of these calls is to give info to the backend about abstract locks. I looked at the llvm.annotation intrinsic, but since it uses a global string, I thought references to variable names (inside the global string) etc may not remain consistent in wake of front-end refactoring/optimizations. My current plan is to:
>
> Create a custom Pragma Handler, say, PragmaAbstractLockHandler, that parses the AbstractLock pragma, and depending on whether the annotation is at the interface level or inside client code, create calls to the following functions:
>
> -- For annotations at interface level, insert a call to the following function into a global section:
> void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question.

> -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
> void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables
>
> void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope
>
> The above functions would be immediately processed in the backend as the first pass of opt (by creating appropriate data structures in the backend) and calls will be removed from the bit code -- after creating nonymous functions for the sections of code marked by abstract locks etc..

This makes perfect sense.

> I would greatly appreciate any suggestions on how to go about translating the pragmas to the above functions in clang, or if there might be a better way to achieve the same with other front-end constructs, that will be great. How do I create a HandlePragma method that Lexes till the end of the code section/function declaration, create an Action that adds these functions in source code ?


There's really no way to create a HandlePragma method that lexes until the end of the code section. Typically, what we do is have HandlePragma set some state in the Sema object that indicates the presence of your particular pragma. Then, when Clang parses the corresponding construct (say, a compound statement), the semantic analysis for that compound statement will check whether a #pragma was parsed and perform the appropriate transformations.

       - Doug



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Intrinsic/Custom Function Creation with Pragmas

Douglas Gregor

On Jan 9, 2010, at 10:04 PM, Prakash Prabhu <[hidden email]> wrote:

Hi Doug,

Never mind about the earlier mail. I looked up Lookup.h (!) and was able to code in identifier resolution without much hassle and also the creation of CallExpr's with appropriate calls to the variadic functions. clang really is easy-to-use/modify ... thanks!

Glad to hear it!

  - Doug


On Fri, Jan 8, 2010 at 10:25 PM, Prakash Prabhu <[hidden email]> wrote:
Hi Doug,

Thanks a lot for your reply. I was able to add the #pragma, parse it successfully, determine the functions/compound statements to which they are attached by adding code to Sema's ActOnCompoundStmt() and a new function called from ParseFunctionDeclarator(). For the pragmas associated with the function interface, I am able to generate calls in a global function inside the LLVM bit code (by changing CodeGenModule.cpp) to:

" void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question. "

Multiple pragma's attached to a single block also seem to work (with the help of a pragma stack).

Although some of the above places may not be the best (in terms of their actual semantics and diagnostics/error checking which I may need at some point in the future), right now it gets the job done.

Now, I am at point where I would like to add calls in the LLVM bit code for compound statements. After looking around in the code for a while,  I still do not have a straightforward solution on how to go about generating calls for compound statments as mentioned in my previous mail:

" -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables

void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope "

The main issue is how to generate the Value* passed in as parameters to __AbstractLockInfoAtClientSiteBegin(), after validating that the variables specified in the #pragma:

// L1 is parameterized by x
int x;
x= ...
#pragma AbstractLock L2 x
{
  int tmp;
  tmp = a;
  a = tmp + 1;
}

In the above code, I would like to verify that x is declared and is in scope before I generate a Value* for it in the AbstractLock...Begin function call. I was thinking of the following possibility: In Semantic Actions phase (ActOnCompoundStmt() to be more specific), verify that x is in scope and generate CallExpr before and after the Compound Stmt, wrap this whole triple into a Compound statment and return it. To do this: (a) How do I get access to the variable declaration of 'x' from this point (ActOnCompoundStmt) -- is there a way to walk up the scope tree/AST and at each point look for a declaration of x in some kind of symbol table/declaration structure ? (b) Is there a easy way to create two AST nodes having CallExpr's  to functions that do not have a declaration yet (maybe I need to create the declarations?).

Alternatively, if there is way to verify the scope and find the type of the variables used (given just the identifier name), at the code generation time, that would be great too. 

Thanks, again, for your time!

regards,
Prakash

On Tue, Jan 5, 2010 at 11:15 AM, Douglas Gregor <[hidden email]> wrote:

On Jan 4, 2010, at 2:37 PM, Prakash Prabhu wrote:

> Hi,
>
> I would like to define some custom pragmas of the following kind, where one can associate abstract locks with functions/structured code blocks using annotations:
>
> Abstract Locks at the function interface level:
> #pragma AbstractLock L1
> void foo();
>
> Abstract Locks for anonymous code blocks:
> #pragma AbstractLock L2
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> Abstract locks could even be parameterized and depend additionally on variables live at point of specification/function parameters:
>
> // L1 is parameterized by param1 and param2
> #pragma AbstractLock L1 param1 param2
> void foo(int param1, int param2, int param3);

It might be easier to implement this as a new attribute on functions, since attributes are automatically associated with declarations or types. Then, you can avoid the problem of teaching a #pragma that comes *before* a declaration to associate itself with the correct declaration.

It might look something like:

       void __attribute__((lock(L1, param1, param2))) foo(int param1, int param2, int param3);

> // L1 is parameterized by x
> int x;
> x= ...
> #pragma AbstractLock L2 x
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> I would like to use clang to pre-process these pragmas, create some kind of annotation structure in the emitted bit code, for use in the llvm backend (in one of the opt passes). I was thinking of creating an LLVM intrinsic/Set of Custom function calls to represent the abstract lock information in the bit code -- the functions by themselves do not exist and the only purpose of these calls is to give info to the backend about abstract locks. I looked at the llvm.annotation intrinsic, but since it uses a global string, I thought references to variable names (inside the global string) etc may not remain consistent in wake of front-end refactoring/optimizations. My current plan is to:
>
> Create a custom Pragma Handler, say, PragmaAbstractLockHandler, that parses the AbstractLock pragma, and depending on whether the annotation is at the interface level or inside client code, create calls to the following functions:
>
> -- For annotations at interface level, insert a call to the following function into a global section:
> void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question.

> -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
> void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables
>
> void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope
>
> The above functions would be immediately processed in the backend as the first pass of opt (by creating appropriate data structures in the backend) and calls will be removed from the bit code -- after creating nonymous functions for the sections of code marked by abstract locks etc..

This makes perfect sense.

> I would greatly appreciate any suggestions on how to go about translating the pragmas to the above functions in clang, or if there might be a better way to achieve the same with other front-end constructs, that will be great. How do I create a HandlePragma method that Lexes till the end of the code section/function declaration, create an Action that adds these functions in source code ?


There's really no way to create a HandlePragma method that lexes until the end of the code section. Typically, what we do is have HandlePragma set some state in the Sema object that indicates the presence of your particular pragma. Then, when Clang parses the corresponding construct (say, a compound statement), the semantic analysis for that compound statement will check whether a #pragma was parsed and perform the appropriate transformations.

       - Doug



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Intrinsic/Custom Function Creation with Pragmas

Prakash Prabhu
Hi Doug,

One last question (hopefully this is the last bit of change to the frontend before I move on to the LLVM backend :)). The problem is to specify abstract Lock conditions using #pragmas as below and have them be translated in C functions that return an int:

An abstract lock condition could be specified as follows:

#pragma AbstractLockCondn(AbstractLockName(param1, param2, ...), (<C expression involving params>))

As an example, this is a way by which one could say that a abstract lock L1 is conditioned on variables x and y, where x and y are variables:

#pragma AbstractLockCondn(L1(x,y), (x>y))

What I would like to do is to create a function like the following:

int __L1_Test__(<type of x> x, <type of y> y)
{
  return (x>y);
}

Basically, I can write a #pragma handler in ParsePragma.cpp which will parse the parameters 1 to n. Much as I would like to invoke the Clang Parser for parsing the C expression and returning a AST node (root of expression tree) for the expression, I am doubtful if that is possible: 

I will not know the type of the parameters until I see their use sites, at which point I will look up the types of the variables in the declaration context having the use sites. So I can't expand the macro at the point where it is parsed. What I can do at this point, is to push this information into Sema object.

However, I would know the types at the end of the translation unit at which point I could potentially generate a function declaration in string and if possible, insert it into the Preprocessor/TokenLexer stream and then invoke the parser for parsing this newly generated function. Is this insertion into the preprocessor/TokenLexer stream possible ? Specifically just before the call to Actions.ActOnEndOfTranslationUnit() in Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result), if I can insert the generated function & its body into the TokenLexer and have the parser process it by calling ParseExternalDeclaration(). So my question is: Is it possible to insert the string containing the function body into token/preprocessor stream and have the parser automatically handle it as if it were a function defined by the programmer ?

Thanks for your time!

- Prakash

On Sun, Jan 10, 2010 at 1:54 AM, Douglas Gregor <[hidden email]> wrote:

On Jan 9, 2010, at 10:04 PM, Prakash Prabhu <[hidden email]> wrote:

Hi Doug,

Never mind about the earlier mail. I looked up Lookup.h (!) and was able to code in identifier resolution without much hassle and also the creation of CallExpr's with appropriate calls to the variadic functions. clang really is easy-to-use/modify ... thanks!

Glad to hear it!

  - Doug



On Fri, Jan 8, 2010 at 10:25 PM, Prakash Prabhu <[hidden email][hidden email]> wrote:
Hi Doug,

Thanks a lot for your reply. I was able to add the #pragma, parse it successfully, determine the functions/compound statements to which they are attached by adding code to Sema's ActOnCompoundStmt() and a new function called from ParseFunctionDeclarator(). For the pragmas associated with the function interface, I am able to generate calls in a global function inside the LLVM bit code (by changing CodeGenModule.cpp) to:

" void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question. "

Multiple pragma's attached to a single block also seem to work (with the help of a pragma stack).

Although some of the above places may not be the best (in terms of their actual semantics and diagnostics/error checking which I may need at some point in the future), right now it gets the job done.

Now, I am at point where I would like to add calls in the LLVM bit code for compound statements. After looking around in the code for a while,  I still do not have a straightforward solution on how to go about generating calls for compound statments as mentioned in my previous mail:

" -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables

void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope "

The main issue is how to generate the Value* passed in as parameters to __AbstractLockInfoAtClientSiteBegin(), after validating that the variables specified in the #pragma:

// L1 is parameterized by x
int x;
x= ...
#pragma AbstractLock L2 x
{
  int tmp;
  tmp = a;
  a = tmp + 1;
}

In the above code, I would like to verify that x is declared and is in scope before I generate a Value* for it in the AbstractLock...Begin function call. I was thinking of the following possibility: In Semantic Actions phase (ActOnCompoundStmt() to be more specific), verify that x is in scope and generate CallExpr before and after the Compound Stmt, wrap this whole triple into a Compound statment and return it. To do this: (a) How do I get access to the variable declaration of 'x' from this point (ActOnCompoundStmt) -- is there a way to walk up the scope tree/AST and at each point look for a declaration of x in some kind of symbol table/declaration structure ? (b) Is there a easy way to create two AST nodes having CallExpr's  to functions that do not have a declaration yet (maybe I need to create the declarations?).

Alternatively, if there is way to verify the scope and find the type of the variables used (given just the identifier name), at the code generation time, that would be great too. 

Thanks, again, for your time!

regards,
Prakash

On Tue, Jan 5, 2010 at 11:15 AM, Douglas Gregor <[hidden email][hidden email]> wrote:

On Jan 4, 2010, at 2:37 PM, Prakash Prabhu wrote:

> Hi,
>
> I would like to define some custom pragmas of the following kind, where one can associate abstract locks with functions/structured code blocks using annotations:
>
> Abstract Locks at the function interface level:
> #pragma AbstractLock L1
> void foo();
>
> Abstract Locks for anonymous code blocks:
> #pragma AbstractLock L2
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> Abstract locks could even be parameterized and depend additionally on variables live at point of specification/function parameters:
>
> // L1 is parameterized by param1 and param2
> #pragma AbstractLock L1 param1 param2
> void foo(int param1, int param2, int param3);

It might be easier to implement this as a new attribute on functions, since attributes are automatically associated with declarations or types. Then, you can avoid the problem of teaching a #pragma that comes *before* a declaration to associate itself with the correct declaration.

It might look something like:

       void __attribute__((lock(L1, param1, param2))) foo(int param1, int param2, int param3);

> // L1 is parameterized by x
> int x;
> x= ...
> #pragma AbstractLock L2 x
> {
>   int tmp;
>   tmp = a;
>   a = tmp + 1;
> }
>
> I would like to use clang to pre-process these pragmas, create some kind of annotation structure in the emitted bit code, for use in the llvm backend (in one of the opt passes). I was thinking of creating an LLVM intrinsic/Set of Custom function calls to represent the abstract lock information in the bit code -- the functions by themselves do not exist and the only purpose of these calls is to give info to the backend about abstract locks. I looked at the llvm.annotation intrinsic, but since it uses a global string, I thought references to variable names (inside the global string) etc may not remain consistent in wake of front-end refactoring/optimizations. My current plan is to:
>
> Create a custom Pragma Handler, say, PragmaAbstractLockHandler, that parses the AbstractLock pragma, and depending on whether the annotation is at the interface level or inside client code, create calls to the following functions:
>
> -- For annotations at interface level, insert a call to the following function into a global section:
> void __AbstractLockInfoAtInterface(char* functionName, char* abstractLockName, ...); // the additional parameters are 0/1/2 ... indicating the positional parameters of original function in question.

> -- For annotations at client site, insert call for begin/end of the section that is being abstractly locked:
> void __AbstractLockInfoAtClientSiteBegin(char* abstractLockName, ...); // the additional parameters are Value* representation of the abstract lock parameter variables
>
> void __AbstractLockInfoAtClientSiteEnd(char* abstractLockName); // marks the end of the abstract lock scope
>
> The above functions would be immediately processed in the backend as the first pass of opt (by creating appropriate data structures in the backend) and calls will be removed from the bit code -- after creating nonymous functions for the sections of code marked by abstract locks etc..

This makes perfect sense.

> I would greatly appreciate any suggestions on how to go about translating the pragmas to the above functions in clang, or if there might be a better way to achieve the same with other front-end constructs, that will be great. How do I create a HandlePragma method that Lexes till the end of the code section/function declaration, create an Action that adds these functions in source code ?


There's really no way to create a HandlePragma method that lexes until the end of the code section. Typically, what we do is have HandlePragma set some state in the Sema object that indicates the presence of your particular pragma. Then, when Clang parses the corresponding construct (say, a compound statement), the semantic analysis for that compound statement will check whether a #pragma was parsed and perform the appropriate transformations.

       - Doug




_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Intrinsic/Custom Function Creation with Pragmas

Douglas Gregor

On Jan 13, 2010, at 2:36 PM, Prakash Prabhu wrote:

> An abstract lock condition could be specified as follows:
>
> #pragma AbstractLockCondn(AbstractLockName(param1, param2, ...), (<C  
> expression involving params>))
>
> As an example, this is a way by which one could say that a abstract  
> lock L1 is conditioned on variables x and y, where x and y are  
> variables:
>
> #pragma AbstractLockCondn(L1(x,y), (x>y))
>
> What I would like to do is to create a function like the following:
>
> int __L1_Test__(<type of x> x, <type of y> y)
> {
>   return (x>y);
> }
>
> Basically, I can write a #pragma handler in ParsePragma.cpp which  
> will parse the parameters 1 to n. Much as I would like to invoke the  
> Clang Parser for parsing the C expression and returning a AST node  
> (root of expression tree) for the expression, I am doubtful if that  
> is possible:
>
> I will not know the type of the parameters until I see their use  
> sites, at which point I will look up the types of the variables in  
> the declaration context having the use sites. So I can't expand the  
> macro at the point where it is parsed.

You could know the types of the variables when they are defined, if  
you checked for the presence of this #pragma in ActOnVariableDeclarator.

> What I can do at this point, is to push this information into Sema  
> object.

Right.

> However, I would know the types at the end of the translation unit  
> at which point I could potentially generate a function declaration  
> in string and if possible, insert it into the Preprocessor/
> TokenLexer stream and then invoke the parser for parsing this newly  
> generated function. Is this insertion into the preprocessor/
> TokenLexer stream possible ? Specifically just before the call to  
> Actions.ActOnEndOfTranslationUnit() in Parser::ParseTopLevelDecl
> (DeclGroupPtrTy &Result), if I can insert the generated function &  
> its body into the TokenLexer and have the parser process it by  
> calling ParseExternalDeclaration(). So my question is: Is it  
> possible to insert the string containing the function body into  
> token/preprocessor stream and have the parser automatically handle  
> it as if it were a function defined by the programmer ?


You can probably teach the Preprocessor's EnterTokenStream function to  
do this.

        - Doug
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev