Ejemplo n.º 1
0
/* Ensure that the directories we need exist and are empty.
 *
 * Our base directory has the name:
 *    output/progname-docs/
 * where output/progname is the executable we are producing (without any
 * extension).
 *
 * Within this base directory we have the following:
 *    mkdocs.yml
 *    docs/
 *      *.md
 */
static void doc_setup_dirs(docgen_t* docgen, ast_t* program, pass_opt_t* opt)
{
  assert(docgen != NULL);
  assert(program != NULL);
  assert(opt != NULL);

  // First build our directory strings
  const char* output = opt->output;
  const char* progname = package_filename(ast_child(program));

  docgen->base_dir = doc_cat(output, "/", progname, "-docs/", "",
    &docgen->base_dir_buf_len);

  docgen->sub_dir = doc_cat(docgen->base_dir, "docs/", "", "", "",
    &docgen->sub_dir_buf_len);

  PONY_LOG(opt, VERBOSITY_INFO, ("Writing docs to %s\n", docgen->base_dir));

  // Create and clear out base directory
  pony_mkdir(docgen->base_dir);
  doc_rm_star(docgen->base_dir);

  // Create and clear out sub directory
  pony_mkdir(docgen->sub_dir);
  doc_rm_star(docgen->sub_dir);
}
Ejemplo n.º 2
0
bool codegen(ast_t* program, pass_opt_t* opt)
{
  PONY_LOG(opt, VERBOSITY_MINIMAL, ("Generating\n"));

  pony_mkdir(opt->output);

  compile_t c;
  memset(&c, 0, sizeof(compile_t));

  init_module(&c, program, opt);
  init_runtime(&c);
  genprim_reachable_init(&c, program);

  bool ok;

  if(c.opt->library)
    ok = genlib(&c, program);
  else
    ok = genexe(&c, program);

  codegen_cleanup(&c);
  return ok;
}
Ejemplo n.º 3
0
const char* genobj(compile_t* c)
{
  errors_t* errors = c->opt->check.errors;

  /*
   * Could store the pony runtime as a bitcode file. Build an executable by
   * amalgamating the program and the runtime.
   *
   * For building a library, could generate a .o without the runtime in it. The
   * user then has to link both the .o and the runtime. Would need a flag for
   * PIC or not PIC. Could even generate a .a and maybe a .so/.dll.
   */
  if(c->opt->limit == PASS_LLVM_IR)
  {
    const char* file_o = suffix_filename(c, c->opt->output, "", c->filename,
      ".ll");
    PONY_LOG(c->opt, VERBOSITY_MINIMAL, ("Writing %s\n", file_o));

    char* err;

    if(LLVMPrintModuleToFile(c->module, file_o, &err) != 0)
    {
      errorf(errors, NULL, "couldn't write IR to %s: %s", file_o, err);
      LLVMDisposeMessage(err);
      return NULL;
    }

    return file_o;
  }

  if(c->opt->limit == PASS_BITCODE)
  {
    const char* file_o = suffix_filename(c, c->opt->output, "", c->filename,
      ".bc");
    PONY_LOG(c->opt, VERBOSITY_MINIMAL, ("Writing %s\n", file_o));

    if(LLVMWriteBitcodeToFile(c->module, file_o) != 0)
    {
      errorf(errors, NULL, "couldn't write bitcode to %s", file_o);
      return NULL;
    }

    return file_o;
  }

  LLVMCodeGenFileType fmt;
  const char* file_o;

  if(c->opt->limit == PASS_ASM)
  {
    fmt = LLVMAssemblyFile;
    file_o = suffix_filename(c, c->opt->output, "", c->filename, ".s");
  } else {
    fmt = LLVMObjectFile;
#ifdef PLATFORM_IS_WINDOWS
    file_o = suffix_filename(c, c->opt->output, "", c->filename, ".obj");
#else
    file_o = suffix_filename(c, c->opt->output, "", c->filename, ".o");
#endif
  }

  PONY_LOG(c->opt, VERBOSITY_MINIMAL, ("Writing %s\n", file_o));
  char* err;

  if(LLVMTargetMachineEmitToFile(
      c->machine, c->module, (char*)file_o, fmt, &err) != 0
    )
  {
    errorf(errors, NULL, "couldn't create file: %s", err);
    LLVMDisposeMessage(err);
    return NULL;
  }

  return file_o;
}
Ejemplo n.º 4
0
bool gentypes(compile_t* c)
{
  reachable_type_t* t;
  size_t i;

  genprim_builtins(c);

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Data prototypes\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!make_opaque_struct(c, t))
      return false;

    gendesc_type(c, t);
    make_debug_info(c, t);
    make_box_type(c, t);
    make_dispatch(c, t);
    gentrace_prototype(c, t);
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Data types\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!make_struct(c, t))
      return false;

    make_global_instance(c, t);
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Function prototypes\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    make_debug_final(c, t);
    make_pointer_methods(c, t);

    if(!genfun_method_sigs(c, t))
      return false;
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Functions\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!genfun_method_bodies(c, t))
      return false;
  }

  PONY_LOG(c->opt, VERBOSITY_INFO, (" Descriptors\n"));
  i = HASHMAP_BEGIN;

  while((t = reachable_types_next(&c->reachable->types, &i)) != NULL)
  {
    if(!make_trace(c, t))
      return false;

    gendesc_init(c, t);
  }

  return true;
}
Ejemplo n.º 5
0
static bool link_exe(compile_t* c, ast_t* program,
  const char* file_o)
{
#if defined(PLATFORM_IS_MACOSX)
  char* arch = strchr(c->opt->triple, '-');

  if(arch == NULL)
  {
    errorf(NULL, "couldn't determine architecture from %s", c->opt->triple);
    return false;
  }

  const char* file_exe = suffix_filename(c->opt->output, "", c->filename, "");
  PONY_LOG(c->opt, VERBOSITY_DEFAULT, ("Linking %s\n", file_exe));

  program_lib_build_args(program, "-L", "", "", "-l", "");
  const char* lib_args = program_lib_args(program);

  size_t arch_len = arch - c->opt->triple;
  size_t ld_len = 128 + arch_len + strlen(file_exe) + strlen(file_o) +
    strlen(lib_args);
  char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len);

  // Avoid incorrect ld, eg from macports.
  snprintf(ld_cmd, ld_len,
    "/usr/bin/ld -execute -no_pie -dead_strip -arch %.*s "
    "-macosx_version_min 10.8 -o %s %s %s -lponyrt -lSystem",
    (int)arch_len, c->opt->triple, file_exe, file_o, lib_args
    );

  PONY_LOG(c->opt, VERBOSITY_TOOL_INFO, ("%s\n", ld_cmd));

  if(system(ld_cmd) != 0)
  {
    errorf(NULL, "unable to link: %s", ld_cmd);
    ponyint_pool_free_size(ld_len, ld_cmd);
    return false;
  }

  ponyint_pool_free_size(ld_len, ld_cmd);

  if(!c->opt->strip_debug)
  {
    size_t dsym_len = 16 + strlen(file_exe);
    char* dsym_cmd = (char*)ponyint_pool_alloc_size(dsym_len);

    snprintf(dsym_cmd, dsym_len, "rm -rf %s.dSYM", file_exe);
    system(dsym_cmd);

    snprintf(dsym_cmd, dsym_len, "dsymutil %s", file_exe);

    if(system(dsym_cmd) != 0)
      errorf(NULL, "unable to create dsym");

    ponyint_pool_free_size(dsym_len, dsym_cmd);
  }

#elif defined(PLATFORM_IS_LINUX) || defined(PLATFORM_IS_FREEBSD)
  const char* file_exe = suffix_filename(c->opt->output, "", c->filename, "");
  PONY_LOG(c->opt, VERBOSITY_DEFAULT, ("Linking %s\n", file_exe));

  program_lib_build_args(program, "-L", "-Wl,--start-group ",
    "-Wl,--end-group ", "-l", "");
  const char* lib_args = program_lib_args(program);

  size_t ld_len = 512 + strlen(file_exe) + strlen(file_o) + strlen(lib_args);
  char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len);

  snprintf(ld_cmd, ld_len, PONY_COMPILER " -o %s -O3 -march=" PONY_ARCH " "
#ifndef PLATFORM_IS_ILP32
    "-mcx16 "
#endif

#ifdef PONY_USE_LTO
    "-flto -fuse-linker-plugin "
#endif

#ifdef PLATFORM_IS_LINUX
    "-fuse-ld=gold "
#endif
    "%s %s -lponyrt -lpthread "
#ifdef PLATFORM_IS_LINUX
    "-ldl "
#endif
    "-lm",
    file_exe, file_o, lib_args
    );

  PONY_LOG(c->opt, VERBOSITY_TOOL_INFO, ("%s\n", ld_cmd));

  if(system(ld_cmd) != 0)
  {
    errorf(NULL, "unable to link: %s", ld_cmd);
    ponyint_pool_free_size(ld_len, ld_cmd);
    return false;
  }

  ponyint_pool_free_size(ld_len, ld_cmd);
#elif defined(PLATFORM_IS_WINDOWS)
  vcvars_t vcvars;

  if(!vcvars_get(&vcvars))
  {
    errorf(NULL, "unable to link: no vcvars");
    return false;
  }

  const char* file_exe = suffix_filename(c->opt->output, "", c->filename,
    ".exe");
  PONY_LOG(c->opt, VERBOSITY_DEFAULT, ("Linking %s\n", file_exe));

  program_lib_build_args(program, "/LIBPATH:", "", "", "", ".lib");
  const char* lib_args = program_lib_args(program);

  size_t ld_len = 256 + strlen(file_exe) + strlen(file_o) +
    strlen(vcvars.kernel32) + strlen(vcvars.msvcrt) + strlen(lib_args);
  char* ld_cmd = (char*)ponyint_pool_alloc_size(ld_len);

  snprintf(ld_cmd, ld_len,
    "cmd /C \"\"%s\" /DEBUG /NOLOGO /MACHINE:X64 "
    "/OUT:%s "
    "%s "
    "/LIBPATH:\"%s\" "
    "/LIBPATH:\"%s\" "
    "%s ponyrt.lib kernel32.lib msvcrt.lib Ws2_32.lib \"",
    vcvars.link, file_exe, file_o, vcvars.kernel32, vcvars.msvcrt, lib_args
    );

  PONY_LOG(c->opt, VERBOSITY_TOOL_INFO, ("%s\n", ld_cmd));

  if(system(ld_cmd) == -1)
  {
    errorf(NULL, "unable to link: %s", ld_cmd);
    ponyint_pool_free_size(ld_len, ld_cmd);
    return false;
  }

  ponyint_pool_free_size(ld_len, ld_cmd);
#endif

  return true;
}