Re: sparse-llvm incorrect definition of local variables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi

I found additional issues with the handling of variables, in
particular if a variable is declared static inside a function.
Following is an updated set of changes that improve the situation.
These are against my modified code base but should translate easily to
sparse-llvm.

static LLVMValueRef build_local(struct dmr_C *C, struct function *fn,
struct symbol *sym)
{
 const char *name = show_ident(C, sym->ident);
 LLVMTypeRef type = symbol_type(C, fn->module, sym);
 LLVMValueRef result;
 char localname[256] = { 0 };
 snprintf(localname, sizeof localname, "%s_%p", name, sym);
 if (is_static(sym) || is_extern(sym) || is_toplevel(sym)) {
  result = LLVMGetNamedGlobal(fn->module, localname);
  if (!result) {
   result = LLVMAddGlobal(fn->module, type, localname);
   if (!is_extern(sym))
    LLVMSetLinkage(result, LLVMInternalLinkage);
   else
    LLVMSetLinkage(result, LLVMExternalLinkage);
  }
 }
 else {
  /* insert alloca into entry block */
  /* LLVM requires allocas to be at the start */
  LLVMBasicBlockRef entrybbr = LLVMGetEntryBasicBlock(fn->fn);
  /* Use temporary Builder as we don't want to mess the function builder */
  LLVMBuilderRef tmp_builder = LLVMCreateBuilder();
  LLVMValueRef firstins = LLVMGetFirstInstruction(entrybbr);
  if (firstins)
   LLVMPositionBuilderBefore(tmp_builder, firstins);
  else
   LLVMPositionBuilderAtEnd(tmp_builder, entrybbr);
  /* Since multiple locals may have same name but in different scopes we
  append the symbol's address to make each variable unique */
  result = LLVMBuildAlloca(tmp_builder, type, localname);
  LLVMDisposeBuilder(tmp_builder);
 }
 sym->priv = result;
 return result;
}

static LLVMValueRef pseudo_to_value(struct dmr_C *C, struct function
*fn, struct instruction *insn, pseudo_t pseudo)
{
 LLVMValueRef result = NULL;
...
 case PSEUDO_SYM: {
  struct symbol *sym = pseudo->sym;
  struct expression *expr;
  result = (LLVMValueRef)sym->priv;
  if (result)
   return result;
  assert(sym->bb_target == NULL);
  expr = sym->initializer;
  if (expr) {
   switch (expr->type) {
   case EXPR_STRING: {
    const char *s = expr->string->data;
    LLVMValueRef indices[] = { LLVMConstInt(LLVMInt64Type(), 0, 0),
LLVMConstInt(LLVMInt64Type(), 0, 0) };
    LLVMValueRef data;
    data = LLVMAddGlobal(fn->module, LLVMArrayType(LLVMInt8Type(),
strlen(s) + 1), ".str");
    LLVMSetLinkage(data, LLVMPrivateLinkage);
    LLVMSetGlobalConstant(data, 1);
    char *scopy = allocator_allocate(&C->byte_allocator, strlen(s) + 1);
    strcpy(scopy, s);
    LLVMSetInitializer(data, LLVMConstString(scopy, strlen(scopy) + 1, true));
    result = LLVMConstGEP(data, indices, ARRAY_SIZE(indices));
    sym->priv = result;
    break;
   }
   case EXPR_SYMBOL: {
    expression_error(C, expr, "unresolved symbol reference in initializer\n");
    show_expression(C, expr);
    exit(1);
    break;
   }
   case EXPR_VALUE:
    result = build_local(C, fn, sym);
    if (is_static(sym))
     LLVMSetInitializer(result, LLVMConstInt(symbol_type(C,
fn->module, sym), expr->value, 1));
    else
     LLVMBuildStore(fn->builder, LLVMConstInt(symbol_type(C,
fn->module, sym), expr->value, 1), result);
    sym->priv = result;
    break;
   case EXPR_FVALUE:
    result = build_local(C, fn, sym);
    if (is_static(sym))
     LLVMSetInitializer(result, LLVMConstReal(symbol_type(C,
fn->module, sym), expr->fvalue));
    else
     LLVMBuildStore(fn->builder, LLVMConstReal(symbol_type(C,
fn->module, sym), expr->fvalue), result);
    sym->priv = result;
    break;
   default:
    expression_error(C, expr, "unsupported expr type in initializer:
%d\n", expr->type);
    show_expression(C, expr);
    exit(1);
   }
  }
  else {
   const char *name = show_ident(C, sym->ident);
   LLVMTypeRef type = symbol_type(C, fn->module, sym);
   if (LLVMGetTypeKind(type) == LLVMFunctionTypeKind) {
    result = LLVMGetNamedFunction(fn->module, name);
    if (!result)
     result = LLVMAddFunction(fn->module, name, type);
    sym->priv = result;
   }
   else if (is_extern(sym) || is_toplevel(sym)) {
    result = LLVMGetNamedGlobal(fn->module, name);
    if (!result) {
     result = LLVMAddGlobal(fn->module, type, name);
     if (is_extern(sym))
      LLVMSetLinkage(result, LLVMExternalLinkage);
    }
    sym->priv = result;
   }
   else {
    result = build_local(C, fn, sym);
    if (is_static(sym)) {
     LLVMSetInitializer(result, LLVMConstNull(type));
    }
    sym->priv = result;
   }
  }
  break;
 }
 case PSEUDO_VAL: {
...
 return result;
}

static LLVMValueRef output_data(struct dmr_C *C, LLVMModuleRef module,
struct symbol *sym)
{
 struct expression *initializer = sym->initializer;
 LLVMValueRef initial_value = NULL;
 LLVMValueRef data = NULL;
 const char *name;
 if (initializer) {
  switch (initializer->type) {
  case EXPR_VALUE:
   initial_value = LLVMConstInt(symbol_type(C, module, sym),
initializer->value, 1);
   break;
  case EXPR_FVALUE:
   initial_value = LLVMConstReal(symbol_type(C, module, sym),
initializer->fvalue);
   break;
  case EXPR_SYMBOL: {
   struct symbol *sym = initializer->symbol;
   if (sym->ident)
    initial_value = LLVMGetNamedGlobal(module, show_ident(C, sym->ident));
   if (!initial_value)
    initial_value = output_data(C, module, sym);
   break;
  }
  case EXPR_STRING: {
   const char *s = initializer->string->data;
   char *scopy = allocator_allocate(&C->byte_allocator, strlen(s) + 1);
   strcpy(scopy, s);
   initial_value = LLVMConstString(scopy, strlen(scopy) + 1, true);
   break;
  }
  default:
   expression_error(C, initializer, "unsupported expr type in global
data initializer: %d\n", initializer->type);
   show_expression(C, initializer);
  }
  if (!initial_value)
   return NULL;
 } else {
  LLVMTypeRef type = symbol_type(C, module, sym);
  initial_value = LLVMConstNull(type);
 }
 name = show_ident(C, sym->ident);
 if (!sym->priv) {
  if (sym->ident)
   data = LLVMGetNamedGlobal(module, name);
  if (!data)
   data = LLVMAddGlobal(module, LLVMTypeOf(initial_value), name);
  LLVMSetLinkage(data, data_linkage(C, sym));
  if (sym->ctype.modifiers & MOD_CONST)
   LLVMSetGlobalConstant(data, 1);
  if (sym->ctype.modifiers & MOD_TLS)
   LLVMSetThreadLocal(data, 1);
  if (sym->ctype.alignment)
   LLVMSetAlignment(data, sym->ctype.alignment);
  if (!(sym->ctype.modifiers & MOD_EXTERN))
   LLVMSetInitializer(data, initial_value);
  sym->priv = data;
 }
 else {
  data = sym->priv;
  if (!(sym->ctype.modifiers & MOD_EXTERN))
   LLVMSetInitializer(data, initial_value);
 }
 return data;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux