Re: sparse-llvm incorrect definition of local variables

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

 



On 13 March 2017 at 11:16, Dibyendu Majumdar <mobile@xxxxxxxxxxxxxxx> wrote:
> On 7 March 2017 at 00:08, Dibyendu Majumdar <mobile@xxxxxxxxxxxxxxx> wrote:
>> int main(const char *argv[]) {
>>  int values[5];
>>  values[0] = 9;
>>  values[1] = 8;
>>  values[2] = 7;
>>  values[3] = 6;
>>  values[4] = 5;
>>  int *p = &values[4];
>>  return (*p == 5) ? 0 : 1;
>> }
>>
>
> The latest version of the changes I made are given below. This appears
> to help also with simple assignments, and fixes another issue I
> reported when accessing the data from a string.
>
> Changes to symbol:
>
> I added a field in the symbol structure for the backend to save the
> LLVM instruction that creates / allocates the symbol.
>
> struct symbol {
>  ...
>  void *priv;
> };
>
> The remaining changes are in sparse-llvm.c. (Apologies for showing
> extracts here from my modified codebase but this should translate
> easily to sparse).
>
> Firstly in pseudo_to_value() the changes are to do with handling of PSEUDO_SYM:
>
>  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: {
>     assert(0 && "unresolved symbol reference");
>     struct symbol *sym = expr->symbol;
>     result = LLVMGetNamedGlobal(fn->module, show_ident(C, sym->ident));
>     assert(result != NULL);
>     break;
>    }
>    case EXPR_VALUE:
>     result = LLVMConstInt(symbol_type(C, fn->module, sym), expr->value, 1);
>     sym->priv = result;
>     break;
>    case EXPR_FVALUE:
>     result = LLVMConstReal(symbol_type(C, fn->module, sym), expr->fvalue);
>     sym->priv = result;
>     break;
>    default:
>     assert(0);
>    }
>   }
>   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);
>     sym->priv = result;
>    }
>    else {
>     char localname[256] = { 0 };
>     /* 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 */
>     snprintf(localname, sizeof localname, "%s_%p", name, sym);
>     result = LLVMBuildAlloca(tmp_builder, type, localname);
>     LLVMDisposeBuilder(tmp_builder);
>     /* Store the alloca instruction for references to the value later on.
>        TODO - should we convert this to pointer here? */
>     sym->priv = result;
>    }
>   }
>   break;
>  }
>
> Secondly in output_data() I added support for floating types and also
> ensured that the sym->priv is set.
>
> static LLVMValueRef output_data(struct dmr_C *C, LLVMModuleRef module,
> struct symbol *sym)
> {
>  struct expression *initializer = sym->initializer;
>  LLVMValueRef initial_value;
>  LLVMValueRef data;
>  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;
>    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:
>    assert(0);
>   }
>  } else {
>   LLVMTypeRef type = symbol_type(C, module, sym);
>   initial_value = LLVMConstNull(type);
>  }
>  name = show_ident(C, sym->ident);
>  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;
>  return data;
> }

It turns out that the handling of EXPR_VALUE and EXPR_FVALUE doesn't
work if the address is taken of the local variable, so I had to change
this to allocate memory on the stack.

Regards
Dibyendu
--
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