Exemple #1
0
static LLVMValueRef make_trait_list(compile_t* c, gentype_t* g,
  uint32_t* final_count)
{
  // The list is an array of integers.
  uint32_t* tid;
  size_t tid_size;
  uint32_t count = trait_count(c, g, &tid, &tid_size);

  // If we have no traits, return a null pointer to a list.
  if(count == 0)
    return LLVMConstNull(LLVMPointerType(LLVMArrayType(c->i32, 0), 0));

  // Create a constant array of trait identifiers.
  size_t list_size = count * sizeof(LLVMValueRef);
  LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(list_size);

  for(uint32_t i = 0; i < count; i++)
    list[i] = LLVMConstInt(c->i32, tid[i], false);

  LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count);

  // Create a global to hold the array.
  const char* name = genname_traitlist(g->type_name);
  LLVMTypeRef type = LLVMArrayType(c->i32, count);
  LLVMValueRef global = LLVMAddGlobal(c->module, type, name);
  LLVMSetGlobalConstant(global, true);
  LLVMSetLinkage(global, LLVMInternalLinkage);
  LLVMSetInitializer(global, trait_array);

  pool_free_size(tid_size, tid);
  pool_free_size(list_size, list);

  *final_count = count;
  return global;
}
Exemple #2
0
static bool make_struct(compile_t* c, gentype_t* g)
{
  LLVMTypeRef type;
  int extra = 0;

  if(g->underlying != TK_TUPLETYPE)
  {
    type = g->structure;
    extra++;
  } else {
    type = g->primitive;
  }

  if(g->underlying == TK_ACTOR)
    extra++;

  size_t buf_size = (g->field_count + extra) * sizeof(LLVMTypeRef);
  LLVMTypeRef* elements = (LLVMTypeRef*)pool_alloc_size(buf_size);

  // Create the type descriptor as element 0.
  if(g->underlying != TK_TUPLETYPE)
    elements[0] = LLVMPointerType(g->desc_type, 0);

  // Create the actor pad as element 1.
  if(g->underlying == TK_ACTOR)
    elements[1] = c->actor_pad;

  // Get a preliminary type for each field and set the struct body. This is
  // needed in case a struct for the type being generated here is required when
  // generating a field.
  for(int i = 0; i < g->field_count; i++)
  {
    gentype_t field_g;

    if(!gentype_prelim(c, g->fields[i], &field_g))
    {
      pool_free_size(buf_size, elements);
      return false;
    }

    elements[i + extra] = field_g.use_type;
  }

  LLVMStructSetBody(type, elements, g->field_count + extra, false);

  // Create a box type for tuples.
  if(g->underlying == TK_TUPLETYPE)
    make_box_type(c, g);

  pool_free_size(buf_size, elements);
  return true;
}
Exemple #3
0
static bool link_lib(compile_t* c, const char* file_o)
{
#if defined(PLATFORM_IS_POSIX_BASED)
  const char* file_lib = suffix_filename(c->opt->output, "lib", c->filename,
    ".a");
  printf("Archiving %s\n", file_lib);

  size_t len = 32 + strlen(file_lib) + strlen(file_o);
  char* cmd = (char*)pool_alloc_size(len);

  snprintf(cmd, len, "ar -rcs %s %s", file_lib, file_o);

  if(system(cmd) != 0)
  {
    errorf(NULL, "unable to link");
    pool_free_size(len, cmd);
    return false;
  }

  pool_free_size(len, cmd);
#elif defined(PLATFORM_IS_WINDOWS)
  const char* file_lib = suffix_filename(c->opt->output, "", c->filename,
    ".lib");
  printf("Archiving %s\n", file_lib);

  vcvars_t vcvars;

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

  size_t len = 128 + strlen(file_lib) + strlen(file_o);
  char* cmd = (char*)pool_alloc_size(len);

  snprintf(cmd, len, "cmd /C \"\"%s\" /NOLOGO /OUT:%s %s\"", vcvars.ar,
    file_lib, file_o);

  if(system(cmd) == -1)
  {
    errorf(NULL, "unable to link");
    pool_free_size(len, cmd);
    return false;
  }

  pool_free_size(len, cmd);
#endif

  return true;
}
Exemple #4
0
static LLVMTypeRef get_signature(compile_t* c, gentype_t* g, ast_t* fun)
{
  // Get a type for the result.
  ast_t* rtype = ast_childidx(fun, 4);
  gentype_t rtype_g;

  if(!gentype(c, rtype, &rtype_g))
  {
    ast_error(rtype, "couldn't generate result type");
    return NULL;
  }

  // Count the parameters, including the receiver.
  ast_t* params = ast_childidx(fun, 3);
  size_t count = ast_childcount(params) + 1;

  size_t buf_size = count *sizeof(LLVMTypeRef);
  LLVMTypeRef* tparams = (LLVMTypeRef*)pool_alloc_size(buf_size);
  count = 0;

  // Get a type for the receiver.
  tparams[count++] = g->use_type;

  // Get a type for each parameter.
  ast_t* param = ast_child(params);

  while(param != NULL)
  {
    ast_t* ptype = ast_childidx(param, 1);
    gentype_t ptype_g;

    if(!gentype(c, ptype, &ptype_g))
    {
      ast_error(ptype, "couldn't generate parameter type");
      pool_free_size(buf_size, tparams);
      return NULL;
    }

    tparams[count++] = ptype_g.use_type;
    param = ast_sibling(param);
  }

  LLVMTypeRef result = rtype_g.use_type;

  // Generate the function type.
  LLVMTypeRef r = LLVMFunctionType(result, tparams, (int)count, false);

  pool_free_size(buf_size, tparams);
  return r;
}
Exemple #5
0
static LLVMValueRef make_unbox_function(compile_t* c, gentype_t* g,
  const char* name)
{
  LLVMValueRef fun = LLVMGetNamedFunction(c->module, name);

  if(fun == NULL)
    return LLVMConstNull(c->void_ptr);

  // Create a new unboxing function that forwards to the real function.
  LLVMTypeRef f_type = LLVMGetElementType(LLVMTypeOf(fun));
  int count = LLVMCountParamTypes(f_type);

  // If it takes no arguments, it's a special number constructor. Don't put it
  // in the vtable.
  if(count == 0)
    return LLVMConstNull(c->void_ptr);

  size_t buf_size = count *sizeof(LLVMTypeRef);
  LLVMTypeRef* params = (LLVMTypeRef*)pool_alloc_size(buf_size);
  LLVMGetParamTypes(f_type, params);
  LLVMTypeRef ret_type = LLVMGetReturnType(f_type);

  // It's the same type, but it takes the boxed type instead of the primitive
  // type as the receiver.
  params[0] = g->structure_ptr;

  const char* unbox_name = genname_unbox(name);
  LLVMTypeRef unbox_type = LLVMFunctionType(ret_type, params, count, false);
  LLVMValueRef unbox_fun = codegen_addfun(c, unbox_name, unbox_type);
  codegen_startfun(c, unbox_fun, false);

  // Extract the primitive type from element 1 and call the real function.
  LLVMValueRef this_ptr = LLVMGetParam(unbox_fun, 0);
  LLVMValueRef primitive_ptr = LLVMBuildStructGEP(c->builder, this_ptr, 1, "");
  LLVMValueRef primitive = LLVMBuildLoad(c->builder, primitive_ptr, "");

  LLVMValueRef* args = (LLVMValueRef*)pool_alloc_size(buf_size);
  args[0] = primitive;

  for(int i = 1; i < count; i++)
    args[i] = LLVMGetParam(unbox_fun, i);

  LLVMValueRef result = codegen_call(c, fun, args, count);
  LLVMBuildRet(c->builder, result);
  codegen_finishfun(c);

  pool_free_size(buf_size, params);
  pool_free_size(buf_size, args);
  return LLVMConstBitCast(unbox_fun, c->void_ptr);
}
Exemple #6
0
static LLVMValueRef make_trait_list(compile_t* c, gentype_t* g)
{
  // The list is an array of integers.
  uint32_t count = trait_count(c, g);

  // If we have no traits, return a null pointer to a list.
  if(count == 0)
    return LLVMConstNull(LLVMPointerType(LLVMArrayType(c->i32, 0), 0));

  // Sort the trait identifiers.
  size_t tid_size = count * sizeof(uint32_t);
  uint32_t* tid = (uint32_t*)pool_alloc_size(tid_size);

  reachable_type_t* t = reach_type(c->reachable, g->type_name);
  assert(t != NULL);

  size_t i = HASHMAP_BEGIN;
  size_t index = 0;
  reachable_type_t* provide;

  while((provide = reachable_type_cache_next(&t->subtypes, &i)) != NULL)
    tid[index++] = provide->type_id;

  qsort(tid, index, sizeof(uint32_t), cmp_uint32);
  index = unique_uint32(tid, index);

  // Create a constant array of trait identifiers.
  size_t list_size = index * sizeof(LLVMValueRef);
  LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(list_size);

  for(i = 0; i < index; i++)
    list[i] = LLVMConstInt(c->i32, tid[i], false);

  count = (uint32_t)index;
  LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count);

  // Create a global to hold the array.
  const char* name = genname_traitlist(g->type_name);
  LLVMTypeRef type = LLVMArrayType(c->i32, count);
  LLVMValueRef global = LLVMAddGlobal(c->module, type, name);
  LLVMSetGlobalConstant(global, true);
  LLVMSetLinkage(global, LLVMInternalLinkage);
  LLVMSetInitializer(global, trait_array);

  pool_free_size(tid_size, tid);
  pool_free_size(list_size, list);
  return global;
}
Exemple #7
0
// Delete all the files in the specified directory
static void doc_rm_star(const char* path)
{
  assert(path != NULL);

  PONY_ERRNO err;
  PONY_DIRINFO entry;
  PONY_DIRINFO* result;

  PONY_DIR* dir = pony_opendir(path, &err);

  if(dir == NULL)
    return;

  while(pony_dir_entry_next(dir, &entry, &result) && (result != NULL))
  {
    char* name = pony_dir_info_name(result);

    if(strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
    {
      // Delete this file
      size_t buf_len;
      char* buf = doc_cat(path, name, "", "", "", &buf_len);

#ifdef PLATFORM_IS_WINDOWS
      DeleteFile(buf);
#else
      remove(buf);
#endif
      pool_free_size(buf_len, buf);
    }
  }

  pony_closedir(dir);
}
Exemple #8
0
static LLVMValueRef get_prototype(compile_t* c, gentype_t* g, const char *name,
  ast_t* typeargs, ast_t* fun)
{
  // Behaviours and actor constructors also have sender functions.
  bool sender = false;

  switch(ast_id(fun))
  {
    case TK_NEW:
      sender = g->underlying == TK_ACTOR;
      break;

    case TK_BE:
      sender = true;
      break;

    default: {}
  }

  // Get a fully qualified name: starts with the type name, followed by the
  // type arguments, followed by the function name, followed by the function
  // level type arguments.
  const char* funname = genname_fun(g->type_name, name, typeargs);

  // If the function already exists, just return it.
  LLVMValueRef func = LLVMGetNamedFunction(c->module, funname);

  if(func != NULL)
    return func;

  LLVMTypeRef ftype = get_signature(c, g, fun);

  if(ftype == NULL)
    return NULL;

  // If the function exists now, just return it.
  func = LLVMGetNamedFunction(c->module, funname);

  if(func != NULL)
    return func;

  if(sender)
  {
    // Generate the sender prototype.
    const char* be_name = genname_be(funname);
    func = codegen_addfun(c, be_name, ftype);

    // Change the return type to void for the handler.
    size_t count = LLVMCountParamTypes(ftype);
    size_t buf_size = count *sizeof(LLVMTypeRef);
    LLVMTypeRef* tparams = (LLVMTypeRef*)pool_alloc_size(buf_size);
    LLVMGetParamTypes(ftype, tparams);

    ftype = LLVMFunctionType(c->void_type, tparams, (int)count, false);
    pool_free_size(buf_size, tparams);
  }

  // Generate the function prototype.
  return codegen_addfun(c, funname, ftype);
}
Exemple #9
0
static void destroy_large(chunk_t* chunk)
{
  // We could clear the pagemap here.
  if(chunk->m != NULL)
    pool_free_size(chunk->size, chunk->m);

  POOL_FREE(chunk_t, chunk);
}
Exemple #10
0
static LLVMValueRef make_vtable(compile_t* c, gentype_t* g)
{
  uint32_t vtable_size = genfun_vtable_size(c, g);

  if(vtable_size == 0)
    return LLVMConstArray(c->void_ptr, NULL, 0);

  size_t buf_size = vtable_size * sizeof(LLVMValueRef);
  LLVMValueRef* vtable = (LLVMValueRef*)pool_alloc_size(buf_size);
  memset(vtable, 0, buf_size);

  reachable_type_t* t = reach_type(c->reachable, g->type_name);

  size_t i = HASHMAP_BEGIN;
  reachable_method_name_t* n;

  while((n = reachable_method_names_next(&t->methods, &i)) != NULL)
  {
    size_t j = HASHMAP_BEGIN;
    reachable_method_t* m;

    while((m = reachable_methods_next(&n->r_methods, &j)) != NULL)
    {
      const char* fullname = genname_fun(t->name, n->name, m->typeargs);
      token_id t = ast_id(m->r_fun);

      switch(t)
      {
        case TK_NEW:
        case TK_BE:
          if(g->underlying == TK_ACTOR)
            fullname = genname_be(fullname);
          break;

        default: {}
      }

      uint32_t index = m->vtable_index;
      assert(index != (uint32_t)-1);
      assert(vtable[index] == NULL);

      if(g->primitive != NULL)
        vtable[index] = make_unbox_function(c, g, fullname, t);
      else
        vtable[index] = make_function_ptr(c, fullname, c->void_ptr);
    }
  }

  for(uint32_t i = 0; i < vtable_size; i++)
  {
    if(vtable[i] == NULL)
      vtable[i] = LLVMConstNull(c->void_ptr);
  }

  LLVMValueRef r = LLVMConstArray(c->void_ptr, vtable, vtable_size);
  pool_free_size(buf_size, vtable);
  return r;
}
Exemple #11
0
static void destroy_large(chunk_t* chunk)
{
  large_pagemap(chunk->m, chunk->size, NULL);

  if(chunk->m != NULL)
    pool_free_size(chunk->size, chunk->m);

  POOL_FREE(chunk_t, chunk);
}
Exemple #12
0
static void genfun_dwarf(compile_t* c, gentype_t* g, const char *name,
  ast_t* typeargs, ast_t* fun)
{
  if(!codegen_hassource(c))
    return;

  // Get the function.
  const char* funname = genname_fun(g->type_name, name, typeargs);
  LLVMValueRef func = LLVMGetNamedFunction(c->module, funname);
  assert(func != NULL);

  // Count the parameters, including the receiver.
  ast_t* params = ast_childidx(fun, 3);
  size_t count = ast_childcount(params) + 1;

  size_t buf_size = (count + 1) * sizeof(const char*);
  const char** pnames = (const char**)pool_alloc_size(buf_size);
  count = 0;

  // Return value type name and receiver type name.
  pnames[count++] = genname_type(ast_childidx(fun, 4));
  pnames[count++] = g->type_name;

  // Get a type name for each parameter.
  ast_t* param = ast_child(params);

  while(param != NULL)
  {
    ast_t* ptype = ast_childidx(param, 1);
    pnames[count++] = genname_type(ptype);
    param = ast_sibling(param);
  }

  // Dwarf the method type
  dwarf_method(&c->dwarf, fun, name, funname, pnames, count, func);

  // Dwarf the receiver pointer.
  LLVMBasicBlockRef entry = LLVMGetEntryBasicBlock(codegen_fun(c));
  LLVMValueRef argument = codegen_getlocal(c, stringtab("this"));

  dwarf_this(&c->dwarf, fun, g->type_name, entry, argument);

  // Dwarf locals for parameters
  param = ast_child(params);
  size_t index = 1;

  while(param != NULL)
  {
    argument = codegen_getlocal(c, ast_name(ast_child(param)));
    dwarf_parameter(&c->dwarf, param, pnames[index + 1], entry, argument,
      index);
    param = ast_sibling(param);
    index++;
  }

  pool_free_size(buf_size, pnames);
}
Exemple #13
0
void generate_docs(ast_t* program, pass_opt_t* options)
{
  assert(program != NULL);

  if(ast_id(program) != TK_PROGRAM)
    return;

  docgen_t docgen;
  doc_setup_dirs(&docgen, program, options);

  // Open the index and home files
  docgen.index_file = doc_open_file(&docgen, false, "mkdocs", ".yml");
  docgen.home_file = doc_open_file(&docgen, true, "index", ".md");
  docgen.type_file = NULL;

  // Write documentation files
  if(docgen.index_file != NULL && docgen.home_file != NULL)
  {
    ast_t* package = ast_child(program);
    const char* name = package_filename(package);

    fprintf(docgen.home_file, "Packages\n\n");

    fprintf(docgen.index_file, "site_name: %s\n", name);
    fprintf(docgen.index_file, "theme: readthedocs\n");
    fprintf(docgen.index_file, "pages:\n");
    fprintf(docgen.index_file, "- %s: index.md\n", name);

    doc_packages(&docgen, program);
  }

  // Tidy up
  if(docgen.index_file != NULL)
    fclose(docgen.index_file);

  if(docgen.home_file != NULL)
   fclose(docgen.home_file);

  if(docgen.base_dir != NULL)
    pool_free_size(docgen.base_dir_buf_len, (void*)docgen.base_dir);

  if(docgen.sub_dir != NULL)
    pool_free_size(docgen.sub_dir_buf_len, (void*)docgen.sub_dir);
}
Exemple #14
0
void source_close(source_t* source)
{
  if(source == NULL)
    return;

  if(source->m != NULL)
    pool_free_size(source->len, source->m);

  POOL_FREE(source_t, source);
}
Exemple #15
0
void token_free(token_t* token)
{
  if(token == NULL)
    return;

  if(token->printed != NULL)
    pool_free_size(64, token->printed);

  POOL_FREE(token_t, token);
}
Exemple #16
0
static LLVMValueRef make_field_list(compile_t* c, gentype_t* g)
{
  // The list is an array of field descriptors.
  int count;

  if(g->underlying == TK_TUPLETYPE)
    count = g->field_count;
  else
    count = 0;

  LLVMTypeRef type = LLVMArrayType(c->field_descriptor, count);

  // If we aren't a tuple, return a null pointer to a list.
  if(count == 0)
    return LLVMConstNull(LLVMPointerType(type, 0));

  // Create a constant array of field descriptors.
  size_t buf_size = count *sizeof(LLVMValueRef);
  LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(buf_size);

  for(int i = 0; i < count; i++)
  {
    gentype_t fg;

    if(!gentype(c, g->fields[i], &fg))
      return NULL;

    LLVMValueRef fdesc[2];
    fdesc[0] = LLVMConstInt(c->i32,
      LLVMOffsetOfElement(c->target_data, g->primitive, i), false);

    if(fg.desc != NULL)
    {
      // We are a concrete type.
      fdesc[1] = LLVMConstBitCast(fg.desc, c->descriptor_ptr);
    } else {
      // We aren't a concrete type.
      fdesc[1] = LLVMConstNull(c->descriptor_ptr);
    }

    list[i] = LLVMConstStructInContext(c->context, fdesc, 2, false);
  }

  LLVMValueRef field_array = LLVMConstArray(c->field_descriptor, list, count);

  // Create a global to hold the array.
  const char* name = genname_fieldlist(g->type_name);
  LLVMValueRef global = LLVMAddGlobal(c->module, type, name);
  LLVMSetGlobalConstant(global, true);
  LLVMSetLinkage(global, LLVMInternalLinkage);
  LLVMSetInitializer(global, field_array);

  pool_free_size(buf_size, list);
  return global;
}
Exemple #17
0
void buildflagset_free(buildflagset_t* set)
{
  if(set != NULL)
  {
    flagtab_destroy(set->flags);
    POOL_FREE(flagtab_t, set->flags);

    if(set->buffer_size > 0)
      pool_free_size(set->buffer_size, set->text_buffer);

    POOL_FREE(buildflagset_t, set);
  }
}
Exemple #18
0
static void add_dispatch_case(compile_t* c, gentype_t* g, ast_t* fun,
  uint32_t index, LLVMValueRef handler, LLVMTypeRef type)
{
  // Add a case to the dispatch function to handle this message.
  codegen_startfun(c, g->dispatch_fn, false);
  LLVMBasicBlockRef block = codegen_block(c, "handler");
  LLVMValueRef id = LLVMConstInt(c->i32, index, false);
  LLVMAddCase(g->dispatch_switch, id, block);

  // Destructure the message.
  LLVMPositionBuilderAtEnd(c->builder, block);
  LLVMValueRef ctx = LLVMGetParam(g->dispatch_fn, 0);
  LLVMValueRef this_ptr = LLVMGetParam(g->dispatch_fn, 1);
  LLVMValueRef msg = LLVMBuildBitCast(c->builder,
    LLVMGetParam(g->dispatch_fn, 2), type, "");

  int count = LLVMCountParams(handler);
  size_t buf_size = count * sizeof(LLVMValueRef);
  LLVMValueRef* args = (LLVMValueRef*)pool_alloc_size(buf_size);
  args[0] = LLVMBuildBitCast(c->builder, this_ptr, g->use_type, "");

  // Trace the message.
  LLVMValueRef start_trace = gencall_runtime(c, "pony_gc_recv", &ctx, 1, "");
  ast_t* params = ast_childidx(fun, 3);
  ast_t* param = ast_child(params);
  bool need_trace = false;

  for(int i = 1; i < count; i++)
  {
    LLVMValueRef field = LLVMBuildStructGEP(c->builder, msg, i + 2, "");
    args[i] = LLVMBuildLoad(c->builder, field, "");

    need_trace |= gentrace(c, ctx, args[i], ast_type(param));
    param = ast_sibling(param);
  }

  if(need_trace)
  {
    gencall_runtime(c, "pony_recv_done", &ctx, 1, "");
  } else {
    LLVMInstructionEraseFromParent(start_trace);
  }

  // Call the handler.
  codegen_call(c, handler, args, count);
  LLVMBuildRetVoid(c->builder);
  codegen_finishfun(c);
  pool_free_size(buf_size, args);
}
Exemple #19
0
static LLVMValueRef assign_to_tuple(compile_t* c, LLVMTypeRef l_type,
  LLVMValueRef r_value, ast_t* type)
{
  // Cast each component.
  assert(ast_id(type) == TK_TUPLETYPE);

  int count = LLVMCountStructElementTypes(l_type);
  size_t buf_size = count * sizeof(LLVMTypeRef);
  LLVMTypeRef* elements = (LLVMTypeRef*)pool_alloc_size(buf_size);
  LLVMGetStructElementTypes(l_type, elements);

  LLVMValueRef result = LLVMGetUndef(l_type);

  ast_t* type_child = ast_child(type);
  int i = 0;

  while(type_child != NULL)
  {
    LLVMValueRef r_child = LLVMBuildExtractValue(c->builder, r_value, i, "");
    LLVMValueRef cast_value = gen_assign_cast(c, elements[i], r_child,
      type_child);

    if(cast_value == NULL)
    {
      pool_free_size(buf_size, elements);
      return NULL;
    }

    result = LLVMBuildInsertValue(c->builder, result, cast_value, i, "");
    type_child = ast_sibling(type_child);
    i++;
  }

  pool_free_size(buf_size, elements);
  return result;
}
Exemple #20
0
// Write the given package home page to its own file
static void doc_package_home(docgen_t* docgen, ast_t* package,
  ast_t* doc_string)
{
  assert(docgen != NULL);
  assert(docgen->index_file != NULL);
  assert(docgen->home_file != NULL);
  assert(docgen->type_file == NULL);
  assert(package != NULL);
  assert(ast_id(package) == TK_PACKAGE);

  // First open a file
  size_t tqfn_len;
  char* tqfn = write_tqfn(package, "-index", &tqfn_len);

  // Package group
  fprintf(docgen->index_file, "- package %s:\n",
    package_qualified_name(package));

  docgen->type_file = doc_open_file(docgen, true, tqfn, ".md");

  if(docgen->type_file == NULL)
    return;

  // Add reference to new file to index file
  fprintf(docgen->index_file, "  - Package: \"%s.md\"\n", tqfn);

  // Add reference to package to home file
  fprintf(docgen->home_file, "* [%s](%s)\n", package_qualified_name(package),
    tqfn);

  // Now we can write the actual documentation for the package
  if(doc_string != NULL)
  {
    assert(ast_id(doc_string) == TK_STRING);
    fprintf(docgen->type_file, "%s", ast_name(doc_string));
  }
  else
  {
    fprintf(docgen->type_file, "No package doc string provided for %s.",
      package_qualified_name(package));
  }

  pool_free_size(tqfn_len, tqfn);

  fclose(docgen->type_file);
  docgen->type_file = NULL;
}
Exemple #21
0
static uint32_t trait_count(compile_t* c, gentype_t* g,
  uint32_t** list, size_t* list_size)
{
  switch(g->underlying)
  {
    case TK_PRIMITIVE:
    case TK_CLASS:
    case TK_ACTOR:
    {
      reachable_type_t* t = reach_type(c->reachable, g->type_name);
      assert(t != NULL);
      uint32_t count = (uint32_t)reachable_type_cache_size(&t->subtypes);

      if(count == 0)
        return 0;

      // Sort the trait identifiers.
      size_t tid_size = count * sizeof(uint32_t);
      uint32_t* tid = (uint32_t*)pool_alloc_size(tid_size);

      size_t i = HASHMAP_BEGIN;
      size_t index = 0;
      reachable_type_t* provide;

      while((provide = reachable_type_cache_next(&t->subtypes, &i)) != NULL)
        tid[index++] = provide->type_id;

      qsort(tid, index, sizeof(uint32_t), cmp_uint32);
      count = (uint32_t)unique_uint32(tid, index);

      if(list != NULL)
      {
        *list = tid;
        *list_size = tid_size;
      } else {
        pool_free_size(tid_size, tid);
      }

      return count;
    }

    default: {}
  }

  return 0;
}
Exemple #22
0
// Free everything we've allocated
static void painter_tidy(painter_t* painter)
{
  assert(painter != NULL);

  size_t map_byte_count = painter->typemap_size * sizeof(uint64_t);

  name_records_destroy(&painter->names);

  colour_record_t* c = painter->colours;

  while(c != NULL)
  {
    colour_record_t* next = c->next;
    pool_free_size(map_byte_count, c->type_map);
    POOL_FREE(sizeof(colour_record_t), c);
    c = next;
  }
}
Exemple #23
0
// Append the given character to the current token text
static void append_to_token(lexer_t* lexer, char c)
{
  if(lexer->buflen >= lexer->alloc)
  {
    size_t new_len = (lexer->alloc > 0) ? lexer->alloc << 1 : 64;
    char* new_buf = (char*)pool_alloc_size(new_len);
    memcpy(new_buf, lexer->buffer, lexer->alloc);

    if(lexer->alloc > 0)
      pool_free_size(lexer->alloc, lexer->buffer);

    lexer->buffer = new_buf;
    lexer->alloc = new_len;
  }

  lexer->buffer[lexer->buflen] = c;
  lexer->buflen++;
}
Exemple #24
0
const char* buildflagset_print(buildflagset_t* set)
{
  assert(set != NULL);
  assert(set->flags != NULL);

  char* p = set->text_buffer;

  // First the mutually exclusive flags.
  if(set->have_os_flags)
    print_flag(_os_flags[set->enum_os_flags], true, set, &p);

  if(set->have_size_flags)
    print_flag(_size_flags[set->enum_size_flags], true, set, &p);

  // Next the normal flags, in any order.
  size_t i = HASHMAP_BEGIN;
  flag_t* flag;

  while((flag = flagtab_next(set->flags, &i)) != NULL)
    print_flag(flag->name, flag->value, set, &p);

  if(p == set->text_buffer) // No flags, all configs match.
    print_str("all configs", set, &p);

  // Check buffer was big enough for it all.
  size_t size_needed = (p - set->text_buffer) + 1; // +1 for terminator.

  if(size_needed > set->buffer_size)
  {
    // Buffer we have isn't big enough, make it bigger then go round again.
    if(set->buffer_size > 0)
      pool_free_size(set->buffer_size, set->text_buffer);

    set->text_buffer = (char*)pool_alloc_size(size_needed);
    set->buffer_size = size_needed;
    set->text_buffer[0] = '\0';
    buildflagset_print(set);
  }

  // Add terminator.
  assert(set->text_buffer != NULL);
  set->text_buffer[size_needed - 1] = '\0';
  return set->text_buffer;
}
Exemple #25
0
const char* suffix_filename(const char* dir, const char* prefix,
  const char* file, const char* extension)
{
  // Copy to a string with space for a suffix.
  size_t len = strlen(dir) + strlen(prefix) + strlen(file) + strlen(extension)
    + 4;
  char* filename = (char*)pool_alloc_size(len);

  // Start with no suffix.
#ifdef PLATFORM_IS_WINDOWS
  snprintf(filename, len, "%s\\%s%s%s", dir, prefix, file, extension);
#else
  snprintf(filename, len, "%s/%s%s%s", dir, prefix, file, extension);
#endif

  int suffix = 0;

  while(suffix < 100)
  {
    // Overwrite files but not directories.
    struct stat s;
    int err = stat(filename, &s);

    if((err == -1) || !S_ISDIR(s.st_mode))
      break;

#ifdef PLATFORM_IS_WINDOWS
    snprintf(filename, len, "%s\\%s%s%d%s", dir, prefix, file, ++suffix,
      extension);
#else
    snprintf(filename, len, "%s/%s%s%d%s", dir, prefix, file, ++suffix,
      extension);
#endif
  }

  if(suffix >= 100)
  {
    errorf(NULL, "couldn't pick an unused file name");
    pool_free_size(len, filename);
    return NULL;
  }

  return stringtab_consume(filename, len);
}
Exemple #26
0
source_t* source_open(const char* file)
{
  FILE* fp = fopen(file, "rb");

  if(fp == NULL)
  {
    errorf(file, "can't open file");
    return NULL;
  }

  fseek(fp, 0, SEEK_END);
  ssize_t size = ftell(fp);

  if(size < 0)
  {
    errorf(file, "can't determine length of file");
    fclose(fp);
    return NULL;
  }

  fseek(fp, 0, SEEK_SET);

  source_t* source = POOL_ALLOC(source_t);
  source->file = stringtab(file);
  source->m = (char*)pool_alloc_size(size);
  source->len = size;

  ssize_t read = fread(source->m, sizeof(char), size, fp);

  if(read < size)
  {
    errorf(file, "failed to read entire file");
    pool_free_size(source->len, source->m);
    POOL_FREE(source_t, source);
    fclose(fp);
    return NULL;
  }

  fclose(fp);
  return source;
}
Exemple #27
0
// Open a file with the specified info.
// The given filename extension should include a dot if one is needed.
// The returned file handle must be fclosed() with no longer needed.
// If the specified file cannot be opened an error will be generated and NULL
// returned.
static FILE* doc_open_file(docgen_t* docgen, bool in_sub_dir,
  const char* filename, const char* extn)
{
  assert(docgen != NULL);
  assert(filename != NULL);
  assert(extn != NULL);

  // Build the type file name in a buffer.
  // Full file name is:
  //   directory/filenameextn
  const char* dir = in_sub_dir ? docgen->sub_dir : docgen->base_dir;
  size_t buf_len;
  char* buffer = doc_cat(dir, filename, extn, "", "", &buf_len);

  // Now we have the file name open the file
  FILE* file = fopen(buffer, "w");

  if(file == NULL)
    errorf(NULL, "Could not write documentation to file %s", buffer);

  pool_free_size(buf_len, buffer);
  return file;
}
Exemple #28
0
static LLVMValueRef make_trait_list(compile_t* c, gentype_t* g)
{
  // The list is an array of integers.
  uint32_t count = trait_count(c, g);
  LLVMTypeRef type = LLVMArrayType(c->i32, count);

  // If we have no traits, return a null pointer to a list.
  if(count == 0)
    return LLVMConstNull(LLVMPointerType(type, 0));

  // Create a constant array of trait identifiers.
  size_t buf_size = count *sizeof(LLVMValueRef);
  LLVMValueRef* list = (LLVMValueRef*)pool_alloc_size(buf_size);

  reachable_type_t* t = reach_type(c->reachable, g->type_name);
  assert(t != NULL);

  size_t i = HASHMAP_BEGIN;
  size_t index = 0;
  reachable_type_t* provide;

  while((provide = reachable_type_cache_next(&t->subtypes, &i)) != NULL)
    list[index++] = make_type_id(c, provide->name);

  LLVMValueRef trait_array = LLVMConstArray(c->i32, list, count);

  // Create a global to hold the array.
  const char* name = genname_traitlist(g->type_name);
  LLVMValueRef global = LLVMAddGlobal(c->module, type, name);
  LLVMSetGlobalConstant(global, true);
  LLVMSetLinkage(global, LLVMInternalLinkage);
  LLVMSetInitializer(global, trait_array);

  pool_free_size(buf_size, list);
  return global;
}
Exemple #29
0
void heap_free(chunk_t* chunk, void* p)
{
  if(chunk->size >= HEAP_SIZECLASSES)
  {
    if(p == chunk->m)
    {
      pool_free_size(chunk->size, chunk->m);
      chunk->m = NULL;
      chunk->slots = 1;
    }
    return;
  }

  // Calculate the external pointer.
  void* ext = EXTERNAL_PTR(p, chunk->size);

  if(p == ext)
  {
    // Shift to account for smallest allocation size.
    uint32_t slot = FIND_SLOT(ext, chunk->m);

    chunk->slots |= slot;
  }
}
Exemple #30
0
static bool make_struct(compile_t* c, gentype_t* g)
{
  LLVMTypeRef type;
  int extra = 0;

  if(g->underlying != TK_TUPLETYPE)
  {
    type = g->structure;

    if(g->underlying != TK_STRUCT)
      extra++;
  } else {
    type = g->primitive;
  }

  if(g->underlying == TK_ACTOR)
    extra++;

  size_t buf_size = (g->field_count + extra) * sizeof(LLVMTypeRef);
  LLVMTypeRef* elements = (LLVMTypeRef*)pool_alloc_size(buf_size);

  // Create the type descriptor as element 0.
  if(extra > 0)
    elements[0] = LLVMPointerType(g->desc_type, 0);

  // Create the actor pad as element 1.
  if(g->underlying == TK_ACTOR)
    elements[1] = c->actor_pad;

  // Get a preliminary type for each field and set the struct body. This is
  // needed in case a struct for the type being generated here is required when
  // generating a field.
  for(int i = 0; i < g->field_count; i++)
  {
    gentype_t field_g;
    bool ok;

    if((g->field_keys != NULL) && (g->field_keys[i] == TK_EMBED))
    {
      ok = gentype(c, g->fields[i], &field_g);
      elements[i + extra] = field_g.structure;
    } else {
      ok = gentype_prelim(c, g->fields[i], &field_g);
      elements[i + extra] = field_g.use_type;
    }

    if(!ok)
    {
      pool_free_size(buf_size, elements);
      return false;
    }
  }

  // An embedded field may have caused the current type to be fully generated
  // at this point. If so, finish gracefully.
  if(!LLVMIsOpaqueStruct(type))
  {
    g->done = true;
    return true;
  }

  LLVMStructSetBody(type, elements, g->field_count + extra, false);

  // Create a box type for tuples.
  if(g->underlying == TK_TUPLETYPE)
    make_box_type(c, g);

  pool_free_size(buf_size, elements);
  return true;
}