[cfe-dev] A howto or template for adding a transformation pass

Hiren Patel hirenvt at gmail.com
Sat Aug 9 12:14:31 PDT 2008


>
> My apologies for the vague question formulation. I'll explain my objective
> with an example.
>
> My initial source is as follows:
> unsigned int fib(unsigned int m) {
>   unsigned int f0 = 0 ;
>   unsigned int f1 = 1, f2, i ;
>   unsigned int l1 = 0;
>   if (m <= 1)  {
>     MARKSTART();
>     printf("Return\n");
>     MARKEND();
>     return m;
>   } else {
>     for (i = 2; i <=m; i++) {
>       f2 = f0 + f1;
>       f0 = f1;
>       f1 = f2;
>       for (l1 = 0; l1 <5; l1++) {
>         printf("woof\n");
>         MARKSTART();
>       }
>       MARKEND();
>       MARKSTART();
>     }
>     MARKEND();
>     return f2;
>   }
> }
>
> The MARKSTART and MARKEND represent MACROs that implement a certain
> instruction in a particular processor. The semantics of the MARKEND and
> MARKSTART can be simply thought of as starting and stopping cycle timers for
> segments of code between the MARKSTART and MARKEND. The resulting code after
> the transformation is as follows:
> unsigned int fib(unsigned int m) {
>   unsigned int f0 = 0 ;
>   unsigned int f1 = 1, f2, i ;
>   unsigned int l1 = 0;
>   if (m <= 1)  {
>     MARKSTART0("fib_seq0");
>     printf("Return\n");
>     MARKEND0("fib_seq0");
>     return m;
>   } else {
>     for (i = 2; i <=m; i++) {
>       MARKSTARTCOUNT("bb_k");
>       f2 = f0 + f1;
>       f0 = f1;
>       f1 = f2;
>       MARKENDCOUNT("bb_k");
>       for (l1 = 0; l1 <5; l1++) {
>         printf("woof\n");
>         MARKSTART2("fib_loop1");
>       }
>       MARKEND2("fib_loop1");
>       MARKSTART1("fib_loop0");
>     }
>     MARKEND1("fib_loop0");
>     return f2;
>   }
> }
>
> The number after a MARKSTART and MARKEND denotes a timer in the processor
> and the string, a unique label identifying blocks of interest used during
> profiling this code. We have certain rules that form a block, such as, a
> MARKSTART must always follow by a MARKEND and use of timers must be
> correctly nested. Notice the MARK*COUNT as only one example of labeling one
> basic block in the source. I would like to add these for every BB in the CFG
> as well. So the tasks here are:
>
> - Identify MARKSTART and MARKEND, allocate a cycle timer such that there
> are no conflicts between the START and END of a block.
> - Identify MARKSTART and MARKEND, add a unique label used in profiling. The
> labels much match the START and END that form a block.
> - For every basic block, add MARKSTARTCOUNT and MARKENDCOUNT respectively
> with a unique BB label.
>
>
>    Are you talking about determining where in a function/method body you
> would want to insert code, or are you scanning for particular statements to
> replace?
>
> I want to scan the methods and insert code as described above. There are
> two levels of source changes: a) MARKSTARTCOUNTs from basic block
> information and b) transformation of MARKSTART and MARKENDs with unique
> labels and timer numbers.
>
>
>
> 2. Replace the statements with certain macros with additional labels.
>
>
> Which statements are you replacing?  Inserting macros should be fairly
> straightforward by using the rewriter (this is a textual translation by
> editing the source code, not editing the ASTs).
>
> I believe the translation for MARKSTART and MARKEND are possible in the
> straightforward manner. However, I'm not so sure about the basic block
> information.
>
>
> 4. Output the changed C file.
>
>
> If you are using the rewriter to do your edits, this is very
> straightforward.  I would like at how the Objective-C -> C translator
> (RewriteObjC) uses the Rewriter to make edits to the source file and then
> blast the new source to disk.
>
>
>
> I've successfully tried the following:
>
> - Added an Analysis consumer, but I noticed that this Analysis consumer
> method is invoked twice; once for each function in the C source. I'd like to
> have access to the full Analysis and then walk it using walker methods.
> - Added an ASTConsumer, but again, this is invoked twice. Once per
> function.
>
>
> I'm not certain what you mean by the "invoked twice" part.  ASTConsumer
> implements an action/visitor interface where it receives callbacks for each
> top level declaration (HandleTopLevelDecl) as well as a single call back
> once the entire translation unit has been parsed (HandleTranslationUnit).
>
> Sorry. I sort of figured this out while learning more about clang.
>
>
>
> My gut feeling is that you want to use the Objective-C rewriter as your
> model, and that you want to rewrite pieces of the C source file by removing
> some statements and inserting others.  You're probably just going to want to
> write a fresh ASTConsumer that contains a Rewriter object.  You can either
> scan for functions/methods to edit using HandleTopLevelDecl, or you can wait
> until HandleTranslationUnit is called to scan all the declarations at once.
> In HandleTranlsationUnit you would also call the appropriate methods on the
> Rewriter to emit your changed source code to disk.  If you need CFGs, it's
> very easy to create a CFG using a single method: CFG::BuildCFG (just pass as
> an argument the Stmt* that represents the body of the function or method you
> want to analyze).
>
> I will look more closely into the rewriter.
>
> Many thanks for your detailed responses.
>
> Regards,
> ~Hiren
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20080809/69c4182f/attachment.html>


More information about the cfe-dev mailing list