Skip to content

Commit

Permalink
Add basic compiler plugins (#2566)
Browse files Browse the repository at this point in the history
This change adds a framework for compiler plugins. Plugins are
specified through the new `--plugin` command line option and can
observe the compiler data structures at various stages of the
compilation process. Only read-only plugins are supported.

An example of this functionality is a plugin that reports detailed
metrics about the compilation process.
  • Loading branch information
Benoit Vey authored and jemc committed Feb 28, 2018
1 parent 97b4829 commit 9f9256e
Show file tree
Hide file tree
Showing 14 changed files with 470 additions and 48 deletions.
1 change: 1 addition & 0 deletions src/common/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ inline uint64_t __pony_clzl(uint64_t x)
# error "Clang doesn't support `static_assert` or `_Static_assert`."
# endif
#else
# include <assert.h>
# define pony_static_assert(c, m) static_assert(c, m)
#endif

Expand Down
8 changes: 6 additions & 2 deletions src/libponyc/ast/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,17 @@
// The private bits of the flags values
enum
{
AST_ORPHAN = 0x10,
AST_ORPHAN = 0x20,
AST_INHERIT_FLAGS = (AST_FLAG_CAN_ERROR | AST_FLAG_CAN_SEND |
AST_FLAG_MIGHT_SEND | AST_FLAG_RECURSE_1 | AST_FLAG_RECURSE_2),
AST_ALL_FLAGS = 0x3FFFFF
AST_ALL_FLAGS = 0x7FFFFF
};


pony_static_assert((int)PASS_ALL <= (int)AST_FLAG_PASS_MASK, "Wrong pass mask");
pony_static_assert(AST_ORPHAN == (AST_FLAG_PASS_MASK + 1), "Wrong AST_ORPHAN");


struct ast_t
{
token_t* t;
Expand Down
36 changes: 18 additions & 18 deletions src/libponyc/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,24 @@ typedef enum

enum
{
AST_FLAG_PASS_MASK = 0x0F,
AST_FLAG_CAN_ERROR = 0x20,
AST_FLAG_CAN_SEND = 0x40,
AST_FLAG_MIGHT_SEND = 0x80,
AST_FLAG_IN_PARENS = 0x100,
AST_FLAG_AMBIGUOUS = 0x200,
AST_FLAG_BAD_SEMI = 0x400,
AST_FLAG_MISSING_SEMI = 0x800,
AST_FLAG_PRESERVE = 0x1000, // Do not process
AST_FLAG_RECURSE_1 = 0x2000,
AST_FLAG_DONE_1 = 0x4000,
AST_FLAG_ERROR_1 = 0x8000,
AST_FLAG_RECURSE_2 = 0x10000,
AST_FLAG_DONE_2 = 0x20000,
AST_FLAG_ERROR_2 = 0x40000,
AST_FLAG_JUMPS_AWAY = 0x80000, // Jumps away (control flow) without a value.
AST_FLAG_INCOMPLETE = 0x100000, // Not all fields are defined.
AST_FLAG_IMPORT = 0x200000, // Import the referenced package.
AST_FLAG_PASS_MASK = 0x1F,
AST_FLAG_CAN_ERROR = 0x40,
AST_FLAG_CAN_SEND = 0x80,
AST_FLAG_MIGHT_SEND = 0x100,
AST_FLAG_IN_PARENS = 0x200,
AST_FLAG_AMBIGUOUS = 0x400,
AST_FLAG_BAD_SEMI = 0x800,
AST_FLAG_MISSING_SEMI = 0x1000,
AST_FLAG_PRESERVE = 0x2000, // Do not process
AST_FLAG_RECURSE_1 = 0x4000,
AST_FLAG_DONE_1 = 0x8000,
AST_FLAG_ERROR_1 = 0x10000,
AST_FLAG_RECURSE_2 = 0x20000,
AST_FLAG_DONE_2 = 0x40000,
AST_FLAG_ERROR_2 = 0x80000,
AST_FLAG_JUMPS_AWAY = 0x100000, // Jumps away (control flow) without a value.
AST_FLAG_INCOMPLETE = 0x200000, // Not all fields are defined.
AST_FLAG_IMPORT = 0x400000, // Import the referenced package.
};

DECLARE_LIST(astlist, astlist_t, ast_t);
Expand Down
5 changes: 5 additions & 0 deletions src/libponyc/codegen/genexe.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "../reach/paint.h"
#include "../pkg/package.h"
#include "../pkg/program.h"
#include "../plugin/plugin.h"
#include "../type/assemble.h"
#include "../type/lookup.h"
#include "../../libponyrt/mem/pool.h"
Expand Down Expand Up @@ -506,6 +507,8 @@ bool genexe(compile_t* c, ast_t* program)
fprintf(stderr, " Selector painting\n");
paint(&c->reach->types);

plugin_visit_reach(c->reach, c->opt, true);

if(c->opt->limit == PASS_PAINT)
{
ast_free(main_ast);
Expand Down Expand Up @@ -534,6 +537,8 @@ bool genexe(compile_t* c, ast_t* program)

gen_main(c, t_main, t_env);

plugin_visit_compile(c, c->opt);

if(!genopt(c, true))
return false;

Expand Down
6 changes: 6 additions & 0 deletions src/libponyc/codegen/genlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "genobj.h"
#include "genheader.h"
#include "genprim.h"
#include "../plugin/plugin.h"
#include "../reach/paint.h"
#include "../type/assemble.h"
#include "../../libponyrt/mem/pool.h"
Expand Down Expand Up @@ -102,6 +103,9 @@ static bool reachable_actors(compile_t* c, ast_t* program)
if(c->opt->verbosity >= VERBOSITY_INFO)
fprintf(stderr, " Selector painting\n");
paint(&c->reach->types);

plugin_visit_reach(c->reach, c->opt, true);

return true;
}

Expand Down Expand Up @@ -177,6 +181,8 @@ bool genlib(compile_t* c, ast_t* program)
)
return false;

plugin_visit_compile(c, c->opt);

if(!genopt(c, true))
return false;

Expand Down
85 changes: 69 additions & 16 deletions src/libponyc/options/options.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#include "options.h"

#include "../libponyc/ponyc.h"
#include "../libponyc/ast/parserapi.h"
#include "../libponyc/ast/bnfprint.h"
#include "../libponyc/pkg/package.h"
#include "../libponyc/pkg/buildflagset.h"
#include "../libponyc/ast/stringtab.h"
#include "../libponyc/ast/treecheck.h"
#include "../libponyc/options/options.h"
#include "../libponyc/pass/pass.h"
#include <platform.h>
#include "../ponyc.h"
#include "../ast/parserapi.h"
#include "../ast/bnfprint.h"
#include "../pkg/package.h"
#include "../pkg/buildflagset.h"
#include "../ast/stringtab.h"
#include "../ast/treecheck.h"
#include "../pass/pass.h"
#include "../plugin/plugin.h"
#include "../libponyrt/options/options.h"
#include "../libponyrt/mem/pool.h"
#include <platform.h>

#include <string.h>
#include <stdio.h>
Expand Down Expand Up @@ -48,6 +48,7 @@ enum
OPT_STATS,
OPT_LINK_ARCH,
OPT_LINKER,
OPT_PLUGIN,

OPT_VERBOSE,
OPT_PASSES,
Expand Down Expand Up @@ -92,6 +93,7 @@ static opt_arg_t std_args[] =
{"stats", '\0', OPT_ARG_NONE, OPT_STATS},
{"link-arch", '\0', OPT_ARG_REQUIRED, OPT_LINK_ARCH},
{"linker", '\0', OPT_ARG_REQUIRED, OPT_LINKER},
{"plugin", '\0', OPT_ARG_REQUIRED, OPT_PLUGIN},

{"verbose", 'V', OPT_ARG_REQUIRED, OPT_VERBOSE},
{"pass", 'r', OPT_ARG_REQUIRED, OPT_PASSES},
Expand Down Expand Up @@ -159,6 +161,8 @@ static void usage(void)
" =name Default is the host architecture.\n"
" --linker Set the linker command to use.\n"
" =name Default is the compiler used to compile ponyc.\n"
" --plugin Use the specified plugin(s).\n"
" =name\n"
" --define, -D Define which openssl version to use default is " PONY_DEFAULT_SSL "\n"
" =openssl_1.1.0\n"
" =openssl_0.9.0\n"
Expand Down Expand Up @@ -212,6 +216,34 @@ static void usage(void)
);
}

static void print_passes()
{
printf(" ");
size_t cur_len = 2;

for(pass_id p = PASS_PARSE; p < PASS_ALL; p = pass_next(p))
{
const char* name = pass_name(p);
size_t len = strlen(name) + 1; // Add 1 for the comma.

if((cur_len + len) < 80)
{
printf("%s,", name);
cur_len += len;
} else {
printf("\n %s,", name);
cur_len = len + 2;
}
}

const char* name = pass_name(PASS_ALL);

if((cur_len + strlen(name)) < 80)
printf("%s\n", name);
else
printf("\n%s\n", name);
}

#define OPENSSL_LEADER "openssl_"
static const char* valid_openssl_flags[] =
{ OPENSSL_LEADER "1.1.0", OPENSSL_LEADER "0.9.0", NULL };
Expand Down Expand Up @@ -274,7 +306,9 @@ ponyc_opt_process_t ponyc_opt_process(opt_state_t* s, pass_opt_t* opt,
exit_code = special_opt_processing(opt);
if(exit_code != CONTINUE)
return exit_code;


bool wants_help = false;

while((id = ponyint_opt_next(s)) != -1)
{
switch(id)
Expand All @@ -286,8 +320,7 @@ ponyc_opt_process_t ponyc_opt_process(opt_state_t* s, pass_opt_t* opt,
return EXIT_0;

case OPT_HELP:
usage();
return EXIT_0;
wants_help = true; break;
case OPT_DEBUG: opt->release = false; break;
case OPT_BUILDFLAG:
if(is_openssl_flag(s->arg_val))
Expand Down Expand Up @@ -340,6 +373,13 @@ ponyc_opt_process_t ponyc_opt_process(opt_state_t* s, pass_opt_t* opt,
case OPT_STATS: opt->print_stats = true; break;
case OPT_LINK_ARCH: opt->link_arch = s->arg_val; break;
case OPT_LINKER: opt->linker = s->arg_val; break;
case OPT_PLUGIN:
if(!plugin_load(opt, s->arg_val))
{
printf("Error loading plugins: %s\n", s->arg_val);
exit_code = EXIT_255;
}
break;

case OPT_AST: *print_program_ast = true; break;
case OPT_ASTPACKAGE: *print_package_ast = true; break;
Expand Down Expand Up @@ -373,9 +413,8 @@ ponyc_opt_process_t ponyc_opt_process(opt_state_t* s, pass_opt_t* opt,
case OPT_PASSES:
if(!limit_passes(opt, s->arg_val))
{
printf("Invalid pass=%s it should be one of:\n%s", s->arg_val,
" parse,syntax,sugar,scope,import,name,flatten,traits,docs,\n"
" refer,expr,verify,final,reach,paint,ir,bitcode,asm,obj,all\n");
printf("Invalid pass=%s it should be one of:\n", s->arg_val);
print_passes();
exit_code = EXIT_255;
}
break;
Expand All @@ -386,6 +425,20 @@ ponyc_opt_process_t ponyc_opt_process(opt_state_t* s, pass_opt_t* opt,
}
}

if(!plugin_parse_options(opt, s->argc, s->argv))
exit_code = EXIT_255;

if(wants_help)
{
usage();
plugin_print_help(opt);

if(exit_code != EXIT_255)
exit_code = EXIT_0;

return exit_code;
}

for(int i = 1; i < (*s->argc); i++)
{
if(s->argv[i][0] == '-')
Expand Down
Loading

0 comments on commit 9f9256e

Please sign in to comment.