/**************************************************************************/
/*                                                                        */
/*  This file is part of the Frama-C's E-ACSL plug-in.                    */
/*                                                                        */
/*  Copyright (C) 2012-2020                                               */
/*    CEA (Commissariat à l'énergie atomique et aux énergies              */
/*         alternatives)                                                  */
/*                                                                        */
/*  you can redistribute it and/or modify it under the terms of the GNU   */
/*  Lesser General Public License as published by the Free Software       */
/*  Foundation, version 2.1.                                              */
/*                                                                        */
/*  It is distributed in the hope that it will be useful,                 */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
/*  GNU Lesser General Public License for more details.                   */
/*                                                                        */
/*  See the GNU Lesser General Public License version 2.1                 */
/*  for more details (enclosed in the file licenses/LGPLv2.1).            */
/*                                                                        */
/**************************************************************************/

#include "e_acsl_malloc.h"

struct memory_spaces mem_spaces = {
  .rtl_mspace = NULL,
  .heap_mspace = NULL,
  .heap_start = 0,
  .heap_end = 0,
  .heap_mspace_least = 0,
};

/* \brief Create two memory spaces, one for RTL and the other for application
   memory. This function *SHOULD* be called before any allocations are made
   otherwise execution fails */
void eacsl_make_memory_spaces(size_t rtl_size, size_t heap_size) {
  mem_spaces.rtl_mspace = eacsl_create_mspace(rtl_size, 0);
  mem_spaces.heap_mspace = eacsl_create_mspace(heap_size, 0);
  /* Do not use `eacsl_mspace_least_addr` here, as it returns the address of the
     mspace header. */
  mem_spaces.heap_start = (uintptr_t)eacsl_mspace_malloc(mem_spaces.heap_mspace,1);
  mem_spaces.heap_end = mem_spaces.heap_start + heap_size;
  /* Save initial least address of heap memspace. This address is used later
     to check whether memspace has been moved. */
  mem_spaces.heap_mspace_least = (uintptr_t)eacsl_mspace_least_addr(mem_spaces.heap_mspace);
}

void eacsl_destroy_memory_spaces() {
  eacsl_destroy_mspace(mem_spaces.rtl_mspace);
  eacsl_destroy_mspace(mem_spaces.heap_mspace);
}

int is_pow_of_2(size_t x) {
  while (((x & 1) == 0) && x > 1) /* while x is even and > 1 */
    x >>= 1;
  return (x == 1);
}
