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