Core dump on “dereferencing” pointer during an add operation

I’m creating a toy language that is a subset of C language, contains only the simple operation on pointer and array.

For the moment I want to focus my self on the pointer, I want to implement some simple operation on the pointer, such as *p = &i (C style) and also somethings like *p = *p + 2 where *p is a int *p

I’m using Ocaml and I’m working with LLVM 10 from ubuntu PPA, but I’m trying to build now the llvm with assertion enable.

I’m receiving the following error

llc: error: llc: a.bc: error: Load operand is not a pointer type (Producer: 'LLVM10.0.0' Reader: 'LLVM 10.0.0')

It looks like an error on the wrong type, and I’m asking what this wrong type because my program has some problem when I try to compiler *p = *p + 2, but on the other hand I have the correct bheaivod with the following operation *p = &i.

My complete code is reported below

int main() {
  int i;
  i = 2;
  int *p;
  p = &i;
  print(*p);
  return 0;
}

Compile like

; ModuleID = 'MicrocC-module'
source_filename = "MicrocC-module"

declare void @print(i32)

declare i32 @getint()

define i32 @main() {
entry:
  %i = alloca i32
  store i32 2, i32* %i
  %p = alloca i32*
  store i32* %i, i32** %p
  %0 = load i32*, i32** %p
  %1 = load i32, i32* %0
  call void @print(i32 %1)
  ret i32 0
}

The code where I have a problem is the following

int main() {
  int i;
  i = 0;
  int *p;
  p = &i;
  *p = *p + 2;
  print(*p);
  print(i);
  return 0;
}

Terminate with the following error

llc: error: llc: a.bc: error: Load operand is not a pointer type (Producer: 'LLVM10.0.0' Reader: 'LLVM 10.0.0')

To summarize, I’m asking how is the correct process to manage this type of operation on the pointer? there is any big error?

In addition, I reported below some comments on my code generation process and my AST.

AST

type typ =
  | TypInt                             (* Type int                    *)
  | TypBool                            (* Type bool                   *)
  | TypChar                            (* Type char                   *)
  | TypArray of typ * int option       (* Array type                  *)
  | TypPoint of typ                    (* Pointer type                *)
  | TypVoid                            (* Type void                   *)
  [@@deriving show]

and expr = expr_node annotated_node
and expr_node =
  | Access of access                 (* x    or  *p    or  a[e]     *)
  | Assign of access * expr          (* x=e  or  *p=e  or  a[e]=e   *)
  | Addr of access                   (* &x   or  &*p   or  &a[e]    *)
  | ILiteral of int                  (* Integer literal             *)
  | CLiteral of char                 (* Char literal                *)
  | BLiteral of bool                 (* Bool literal                *)
  | UnaryOp of uop * expr            (* Unary primitive operator    *)
  | BinaryOp of binop * expr * expr  (* Binary primitive operator   *)
  | Call of identifier * expr list   (* Function call f(...)        *)
  [@@deriving show]

and access = access_node annotated_node
and access_node =
  | AccVar of identifier             (* Variable access        x    *)
  | AccDeref of expr                 (* Pointer dereferencing  *p   *)
  | AccIndex of access * expr        (* Array indexing         a[e] *)
  [@@deriving show]

Code to generate the accessing to variable

the function applied on access nodes

 | Access (access) ->
    begin
      let var = translate_acc_var access llvm_builder in
      Llvm.build_load var "" llvm_builder
    end
| Addr(access) ->
begin
  logger#debug "* &VAR* Translating .....";
  translate_acc_var access llvm_builder
end

the function applied on access_node

| Ast.AccVar(id) ->
    begin
      logger#trace "Access variable with id %s ...." id;
      try
        begin
          (<-<) id
        end
      with Not_found -> failwith "Variable not found"
    end

   | AccDeref (expr) as node->
        begin
          logger#debug "* *%s * Translating ..." (show_access_node node);
          let llval = translate_exp_to_llvm expr llvm_builder in
          let val_name = Llvm.value_name llval in
          let type_val = Llvm.type_of llval in
          Llvm.build_ptrtoint llval type_val val_name llvm_builder
        end

Where (>->) is an operator to store the value in a map and this map is populated from the following function

let rec translate_stm_to_llvm_ir llvm_builder stm_def =
  match stm_def.node with
  | Ast.Dec(tipe, id) ->
    begin
      logger#debug "Declaration stm processing for type %s" (Ast.show_typ tipe);
      match tipe with
      | Ast.TypArray(arr_tipe, size) ->
        begin
          let llvm_arr = gen_array_type (to_llvm_type arr_tipe) size in
          let llvm_val = Llvm.build_alloca llvm_arr id llvm_builder in
          (>->) id llvm_val false
        end
      | _ ->
        begin
          logger#trace "Literal variable build with LLVM";
          let all_llvm = Llvm.build_alloca (to_llvm_type tipe) id llvm_builder in
          (>->) id all_llvm false
        end
    end

Sorry for the long long question, but I hope it has all the necessary information.

Thanks