<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Creating custom GCC attributes — gcc-python-plugin 0.9 documentation</title> <link rel="stylesheet" href="_static/default.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '', VERSION: '0.9', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> <link rel="top" title="gcc-python-plugin 0.9 documentation" href="index.html" /> <link rel="next" title="Usage example: a static analysis tool for CPython extension code" href="cpychecker.html" /> <link rel="prev" title="Working with callbacks" href="callbacks.html" /> </head> <body> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="genindex.html" title="General Index" accesskey="I">index</a></li> <li class="right" > <a href="cpychecker.html" title="Usage example: a static analysis tool for CPython extension code" accesskey="N">next</a> |</li> <li class="right" > <a href="callbacks.html" title="Working with callbacks" accesskey="P">previous</a> |</li> <li><a href="index.html">gcc-python-plugin 0.9 documentation</a> »</li> </ul> </div> <div class="document"> <div class="documentwrapper"> <div class="bodywrapper"> <div class="body"> <div class="section" id="creating-custom-gcc-attributes"> <h1>Creating custom GCC attributes<a class="headerlink" href="#creating-custom-gcc-attributes" title="Permalink to this headline">¶</a></h1> <p>GNU C supports a non-standard <a class="reference external" href="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html">__attribute__(()) syntax</a> for marking declarations with additional information that may be of interest to the optimizer, and for checking the correctness of the code.</p> <p>The GCC Python plugin allows you to create custom attributes, which may be of use to your scripts: you can use this to annotate C code with additional information. For example, you could create a custom attribute for functions describing the interaction of a function on mutex objects:</p> <div class="highlight-c"><div class="highlight"><pre><span class="k">extern</span> <span class="kt">void</span> <span class="n">some_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__attribute__</span><span class="p">((</span><span class="n">claims_mutex</span><span class="p">(</span><span class="s">"io"</span><span class="p">)));</span> <span class="k">extern</span> <span class="kt">void</span> <span class="n">some_other_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__attribute__</span><span class="p">((</span><span class="n">releases_mutex</span><span class="p">(</span><span class="s">"io"</span><span class="p">)));</span> </pre></div> </div> <p>and use this in a custom code-checker.</p> <p>Custom attributes can take string and integer parameters. For example, the above custom attributes take a single string parameter. A custom attribute can take more than one parameter, or none at all.</p> <p>To create custom attributes from Python, you need to wire up a callback response to the <a class="reference internal" href="callbacks.html#gcc.PLUGIN_ATTRIBUTES" title="gcc.PLUGIN_ATTRIBUTES"><tt class="xref py py-data docutils literal"><span class="pre">gcc.PLUGIN_ATTRIBUTES</span></tt></a> event:</p> <blockquote> <div><div class="highlight-python"><div class="highlight"><pre><span class="n">gcc</span><span class="o">.</span><span class="n">register_callback</span><span class="p">(</span><span class="n">gcc</span><span class="o">.</span><span class="n">PLUGIN_ATTRIBUTES</span><span class="p">,</span> <span class="n">register_our_attributes</span><span class="p">)</span> </pre></div> </div> </div></blockquote> <p>This callback should then call <a class="reference internal" href="#gcc.register_attribute" title="gcc.register_attribute"><tt class="xref py py-func docutils literal"><span class="pre">gcc.register_attribute()</span></tt></a> to associate the name of the attribute with a Python callback to be called when the attribute is encountered in C code.</p> <dl class="function"> <dt id="gcc.register_attribute"> <tt class="descclassname">gcc.</tt><tt class="descname">register_attribute</tt><big>(</big><em>name</em>, <em>min_length</em>, <em>max_length</em>, <em>decl_required</em>, <em>type_required</em>, <em>function_type_required</em>, <em>callable</em><big>)</big><a class="headerlink" href="#gcc.register_attribute" title="Permalink to this definition">¶</a></dt> <dd><p>Registers a new GCC attribute with the given <em>name</em> , usable in C source code via <tt class="docutils literal"><span class="pre">__attribute__(())</span></tt>.</p> <table class="docutils field-list" frame="void" rules="none"> <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> <tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> <li><strong>name</strong> (<em>str</em>) – the name of the new attribute</li> <li><strong>min_length</strong> (<em>int</em>) – the minimum number of arguments expected when the attribute is used</li> <li><strong>max_length</strong> (<em>int</em>) – the maximum number of arguments expected when the attribute is used (-1 for no maximum)</li> <li><strong>decl_required</strong> – </li> <li><strong>type_required</strong> – </li> <li><strong>function_type_required</strong> – </li> <li><strong>callable</strong> (<em>a callable object, such as a function</em>) – the callback to be invoked when the attribute is seen</li> </ul> </td> </tr> </tbody> </table> </dd></dl> <p>In this example, we can simply print when the attribute is seen, to verify that the callback mechanism is working:</p> <blockquote> <div><div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">attribute_callback_for_claims_mutex</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="k">print</span><span class="p">(</span><span class="s">'attribute_callback_for_claims_mutex called: args: </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">))</span> <span class="k">def</span> <span class="nf">attribute_callback_for_releases_mutex</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="k">print</span><span class="p">(</span><span class="s">'attribute_callback_for_releases_mutex called: args: </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">))</span> <span class="k">def</span> <span class="nf">register_our_attributes</span><span class="p">():</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_attribute</span><span class="p">(</span><span class="s">'claims_mutex'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">attribute_callback_for_claims_mutex</span><span class="p">)</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_attribute</span><span class="p">(</span><span class="s">'releases_mutex'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">attribute_callback_for_releases_mutex</span><span class="p">)</span> </pre></div> </div> </div></blockquote> <p>Putting it all together, here is an example Python script for the plugin:</p> <blockquote> <div><div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">gcc</span> <span class="c"># Verify that we can register custom attributes:</span> <span class="k">def</span> <span class="nf">attribute_callback_for_claims_mutex</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="k">print</span><span class="p">(</span><span class="s">'attribute_callback_for_claims_mutex called: args: </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">))</span> <span class="k">def</span> <span class="nf">attribute_callback_for_releases_mutex</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="k">print</span><span class="p">(</span><span class="s">'attribute_callback_for_releases_mutex called: args: </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">))</span> <span class="k">def</span> <span class="nf">register_our_attributes</span><span class="p">():</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_attribute</span><span class="p">(</span><span class="s">'claims_mutex'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">attribute_callback_for_claims_mutex</span><span class="p">)</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_attribute</span><span class="p">(</span><span class="s">'releases_mutex'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">attribute_callback_for_releases_mutex</span><span class="p">)</span> <span class="c"># Wire up our callback:</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_callback</span><span class="p">(</span><span class="n">gcc</span><span class="o">.</span><span class="n">PLUGIN_ATTRIBUTES</span><span class="p">,</span> <span class="n">register_our_attributes</span><span class="p">)</span> </pre></div> </div> </div></blockquote> <p>Compiling this test C source file:</p> <blockquote> <div><div class="highlight-c"><div class="highlight"><pre><span class="cm">/* Function declarations with custom attributes: */</span> <span class="k">extern</span> <span class="n">some_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__attribute__</span><span class="p">((</span><span class="n">claims_mutex</span><span class="p">(</span><span class="s">"io"</span><span class="p">)));</span> <span class="k">extern</span> <span class="n">some_other_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__attribute__</span><span class="p">((</span><span class="n">releases_mutex</span><span class="p">(</span><span class="s">"io"</span><span class="p">)));</span> <span class="k">extern</span> <span class="n">yet_another_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">__attribute__</span><span class="p">((</span><span class="n">claims_mutex</span><span class="p">(</span><span class="s">"db"</span><span class="p">),</span> <span class="n">claims_mutex</span><span class="p">(</span><span class="s">"io"</span><span class="p">),</span> <span class="n">releases_mutex</span><span class="p">(</span><span class="s">"io"</span><span class="p">)));</span> </pre></div> </div> </div></blockquote> <p>leads to this output from the script:</p> <blockquote> <div><div class="highlight-bash"><div class="highlight"><pre>attribute_callback_for_claims_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'some_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> attribute_callback_for_releases_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'some_other_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> attribute_callback_for_claims_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'yet_another_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'db'</span><span class="o">))</span> attribute_callback_for_claims_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'yet_another_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> attribute_callback_for_releases_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'yet_another_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> </pre></div> </div> </div></blockquote> <div class="section" id="using-the-preprocessor-to-guard-attribute-usage"> <h2>Using the preprocessor to guard attribute usage<a class="headerlink" href="#using-the-preprocessor-to-guard-attribute-usage" title="Permalink to this headline">¶</a></h2> <p>Unfortunately, the above C code will only work when it is compiled with the Python script that adds the custom attributes.</p> <p>You can avoid this by using <a class="reference internal" href="preprocessor.html#gcc.define_macro" title="gcc.define_macro"><tt class="xref py py-func docutils literal"><span class="pre">gcc.define_macro()</span></tt></a> to pre-define a preprocessor name (e.g. “WITH_ATTRIBUTE_CLAIMS_MUTEX”) at the same time as when you define the attribute:</p> <blockquote> <div><div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">gcc</span> <span class="k">def</span> <span class="nf">attribute_callback_for_claims_mutex</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="k">print</span><span class="p">(</span><span class="s">'attribute_callback_for_claims_mutex called: args: </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">))</span> <span class="k">def</span> <span class="nf">attribute_callback_for_releases_mutex</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="k">print</span><span class="p">(</span><span class="s">'attribute_callback_for_releases_mutex called: args: </span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">))</span> <span class="k">def</span> <span class="nf">register_our_attributes</span><span class="p">():</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_attribute</span><span class="p">(</span><span class="s">'claims_mutex'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">attribute_callback_for_claims_mutex</span><span class="p">)</span> <span class="n">gcc</span><span class="o">.</span><span class="n">define_macro</span><span class="p">(</span><span class="s">'WITH_ATTRIBUTE_CLAIMS_MUTEX'</span><span class="p">)</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_attribute</span><span class="p">(</span><span class="s">'releases_mutex'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="n">attribute_callback_for_releases_mutex</span><span class="p">)</span> <span class="n">gcc</span><span class="o">.</span><span class="n">define_macro</span><span class="p">(</span><span class="s">'WITH_ATTRIBUTE_RELEASES_MUTEX'</span><span class="p">)</span> <span class="c"># Wire up our callback:</span> <span class="n">gcc</span><span class="o">.</span><span class="n">register_callback</span><span class="p">(</span><span class="n">gcc</span><span class="o">.</span><span class="n">PLUGIN_ATTRIBUTES</span><span class="p">,</span> <span class="n">register_our_attributes</span><span class="p">)</span> </pre></div> </div> </div></blockquote> <p>This way the user can write this C code instead, and have it work both with and without the Python script:</p> <blockquote> <div><div class="highlight-c"><div class="highlight"><pre><span class="cp">#if defined(WITH_ATTRIBUTE_CLAIMS_MUTEX)</span> <span class="cp"> #define CLAIMS_MUTEX(x) __attribute__((claims_mutex(x)))</span> <span class="cp">#else</span> <span class="cp"> #define CLAIMS_MUTEX(x)</span> <span class="cp">#endif</span> <span class="cp">#if defined(WITH_ATTRIBUTE_RELEASES_MUTEX)</span> <span class="cp"> #define RELEASES_MUTEX(x) __attribute__((releases_mutex(x)))</span> <span class="cp">#else</span> <span class="cp"> #define RELEASES_MUTEX(x)</span> <span class="cp">#endif</span> <span class="cm">/* Function declarations with custom attributes: */</span> <span class="k">extern</span> <span class="kt">void</span> <span class="n">some_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">CLAIMS_MUTEX</span><span class="p">(</span><span class="s">"io"</span><span class="p">);</span> <span class="k">extern</span> <span class="kt">void</span> <span class="n">some_other_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">RELEASES_MUTEX</span><span class="p">(</span><span class="s">"io"</span><span class="p">);</span> <span class="k">extern</span> <span class="kt">void</span> <span class="n">yet_another_function</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">CLAIMS_MUTEX</span><span class="p">(</span><span class="s">"db"</span><span class="p">)</span> <span class="n">CLAIMS_MUTEX</span><span class="p">(</span><span class="s">"io"</span><span class="p">)</span> <span class="n">RELEASES_MUTEX</span><span class="p">(</span><span class="s">"io"</span><span class="p">);</span> </pre></div> </div> </div></blockquote> <p>giving this output from the script:</p> <blockquote> <div><div class="highlight-bash"><div class="highlight"><pre>attribute_callback_for_claims_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'some_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> attribute_callback_for_releases_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'some_other_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> attribute_callback_for_claims_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'yet_another_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'db'</span><span class="o">))</span> attribute_callback_for_claims_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'yet_another_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> attribute_callback_for_releases_mutex called: args: <span class="o">(</span>gcc.FunctionDecl<span class="o">(</span><span class="s1">'yet_another_function'</span><span class="o">)</span>, gcc.StringCst<span class="o">(</span><span class="s1">'io'</span><span class="o">))</span> </pre></div> </div> </div></blockquote> </div> </div> </div> </div> </div> <div class="sphinxsidebar"> <div class="sphinxsidebarwrapper"> <h3><a href="index.html">Table Of Contents</a></h3> <ul> <li><a class="reference internal" href="#">Creating custom GCC attributes</a><ul> <li><a class="reference internal" href="#using-the-preprocessor-to-guard-attribute-usage">Using the preprocessor to guard attribute usage</a></li> </ul> </li> </ul> <h4>Previous topic</h4> <p class="topless"><a href="callbacks.html" title="previous chapter">Working with callbacks</a></p> <h4>Next topic</h4> <p class="topless"><a href="cpychecker.html" title="next chapter">Usage example: a static analysis tool for CPython extension code</a></p> <h3>This Page</h3> <ul class="this-page-menu"> <li><a href="_sources/attributes.txt" rel="nofollow">Show Source</a></li> </ul> <div id="searchbox" style="display: none"> <h3>Quick search</h3> <form class="search" action="search.html" method="get"> <input type="text" name="q" /> <input type="submit" value="Go" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> <p class="searchtip" style="font-size: 90%"> Enter search terms or a module, class or function name. </p> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <div class="clearer"></div> </div> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="genindex.html" title="General Index" >index</a></li> <li class="right" > <a href="cpychecker.html" title="Usage example: a static analysis tool for CPython extension code" >next</a> |</li> <li class="right" > <a href="callbacks.html" title="Working with callbacks" >previous</a> |</li> <li><a href="index.html">gcc-python-plugin 0.9 documentation</a> »</li> </ul> </div> <div class="footer"> © Copyright 2011, David Malcolm. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3. </div> </body> </html>