class AdLint::Cc1::VariableTable

Public Class Methods

new(mem_pool) click to toggle source
# File lib/adlint/cc1/object.rb, line 671
def initialize(mem_pool)
  @memory_pool     = mem_pool
  @named_variables = [{}]
  @temp_variables  = [[]]
  @scope_stack     = [GlobalScope.new]
end

Public Instance Methods

all_named_variables() click to toggle source
# File lib/adlint/cc1/object.rb, line 678
def all_named_variables
  @named_variables.map { |hash| hash.values }.flatten
end
begin_variables_value_versioning() click to toggle source
# File lib/adlint/cc1/object.rb, line 773
def begin_variables_value_versioning
  @named_variables.each do |hash|
    hash.each_value { |var| var.begin_value_versioning }
  end
end
declare(dcl, br) click to toggle source
# File lib/adlint/cc1/object.rb, line 700
def declare(dcl, br)
  if var = lookup(dcl.identifier.value)
    var.declarations_and_definitions.push(dcl)
    return var
  end

  # NOTE: External variable may have undefined values.
  define_variable(dcl, br, dcl.type, allocate_memory(dcl),
                  dcl.type.undefined_value)
end
define(dcl_or_def, br, init_val = nil) click to toggle source
# File lib/adlint/cc1/object.rb, line 711
def define(dcl_or_def, br, init_val = nil)
  if storage_duration_of(dcl_or_def) == :static && !dcl_or_def.type.const?
    # NOTE: Value of the inconstant static duration variable should be
    #       arbitrary because execution of its accessors are out of order.
    #       So, a value of the initializer should be ignored.
    init_val = dcl_or_def.type.arbitrary_value
  else
    init_val ||= dcl_or_def.type.undefined_value
  end

  if var = lookup(dcl_or_def.identifier.value)
    if var.scope == current_scope
      var.declarations_and_definitions.push(dcl_or_def)
      var.value.force_overwrite!(init_val.coerce_to(var.type))
      if repr_elem = var.representative_element
        repr_elem.value.force_overwrite!(repr_elem.type.arbitrary_value)
      end
      return var
    end
  end

  # NOTE: Domain of the init-value will be restricted by type's min-max in
  #       define_variable.
  define_variable(dcl_or_def, br, dcl_or_def.type,
                  allocate_memory(dcl_or_def), init_val)
end
define_temporary(type, init_val) click to toggle source
# File lib/adlint/cc1/object.rb, line 738
def define_temporary(type, init_val)
  mem = @memory_pool.allocate_dynamic(type.aligned_byte_size)

  # NOTE: Domain of the init-value will be restricted by type's min-max in
  #       define_variable.
  define_variable(nil, nil, type, mem, init_val)
end
designators() click to toggle source
# File lib/adlint/cc1/object.rb, line 755
def designators
  @named_variables.map { |hash| hash.keys }.flatten.to_set
end
end_variables_value_versioning() click to toggle source
# File lib/adlint/cc1/object.rb, line 779
def end_variables_value_versioning
  @named_variables.each do |hash|
    hash.each_value { |var| var.end_value_versioning }
  end
end
enter_scope() click to toggle source
# File lib/adlint/cc1/object.rb, line 682
def enter_scope
  @named_variables.push({})
  @temp_variables.push([])
  @scope_stack.push(Scope.new(@scope_stack.size))
end
enter_variables_value_versioning_group() click to toggle source
# File lib/adlint/cc1/object.rb, line 759
def enter_variables_value_versioning_group
  @named_variables.each do |hash|
    hash.each_value { |var| var.enter_value_versioning_group }
  end
end
leave_scope() click to toggle source
# File lib/adlint/cc1/object.rb, line 688
def leave_scope
  @named_variables.pop.each_value do |var|
    @memory_pool.free(var.binding.memory)
  end
  @temp_variables.pop.each do |var|
    @memory_pool.free(var.binding.memory)
  end

  @scope_stack.pop
  rollback_all_global_variables_value! if current_scope.global?
end
leave_variables_value_versioning_group(raise_complement) click to toggle source
# File lib/adlint/cc1/object.rb, line 765
def leave_variables_value_versioning_group(raise_complement)
  @named_variables.each do |hash|
    hash.each_value do |var|
      var.leave_value_versioning_group(raise_complement)
    end
  end
end
lookup(name_str) click to toggle source
# File lib/adlint/cc1/object.rb, line 746
def lookup(name_str)
  @named_variables.reverse_each do |hash|
    if var = hash[name_str]
      return var
    end
  end
  nil
end
storage_duration_of(dcl_or_def) click to toggle source
# File lib/adlint/cc1/object.rb, line 791
def storage_duration_of(dcl_or_def)
  # NOTE: The ISO C99 standard says;
  #
  # 6.2.2 Linkages of identifiers
  #
  # 1 An identifier declared in different scopes or in the same scope more
  #   than once can be made to refer to the same object or function by a
  #   process called linkage.  There are three kinds of linkage: external,
  #   internal, and none.
  #
  # 3 If the declaration of a file scope identifier for an object or a
  #   function contains the storage-class specifier static, the identifier
  #   has internal linkage.
  #
  # 4 For an identifier declared with the storage-class specifier extern in
  #   a scope in which a prior declaration of that identifier is visible,
  #   if the prior declaration specifies internal or external linkage, the
  #   linkage of the identifier at the later declaration is the same as the
  #   linkage specified at the prior declaration. If no prior declaration
  #   is visible, or if the prior declaration specifies no linkage, then
  #   the identifier has external linkage.
  #
  # 5 If the declaration of an identifier for a function has no
  #   storage-class specifier, its linkage is determined exactly as if it
  #   were declared with the storage-class specifier extern. If the
  #   declaration of an identifier for an object has file scope and no
  #   storage-class specifier, its linkage is external.
  #
  # 6 The following identifiers have no linkage: an identifier declared to
  #   be anything other than an object or a function; an identifier
  #   declared to be a function parameter; a block scope identifier for an
  #   object declared without the storage-class specifier extern.
  #
  # 6.2.4 Storage durations of objects
  #
  # 1 An object has a storage duration that determines its lifetime. There
  #   are three storage durations: static, automatic, and allocated.
  #   Allocated storage is described in 7.20.3.
  #
  # 3 An object whose identifier is declared with external or internal
  #   linkage, or with the storage-class specifier static has static
  #   storage duration. Its lifetime is the entire execution of the program
  #   and its stored value is initialized only once, prior to program
  #   startup.
  #
  # 4 An object whose identifier is declared with no linkage and without
  #   the storage-class specifier static has automatic storage duration.

  if sc_spec = dcl_or_def.storage_class_specifier and
      sc_spec.type == :EXTERN || sc_spec.type == :STATIC
    :static
  else
    current_scope.global? ? :static : :automatic
  end
end
thin_latest_variables_value_version!(with_rollback) click to toggle source
# File lib/adlint/cc1/object.rb, line 785
def thin_latest_variables_value_version!(with_rollback)
  @named_variables.each do |hash|
    hash.each_value { |var| var.thin_latest_value_version!(with_rollback) }
  end
end

Private Instance Methods

allocate_memory(dcl_or_def) click to toggle source
# File lib/adlint/cc1/object.rb, line 861
def allocate_memory(dcl_or_def)
  byte_size = dcl_or_def.type.aligned_byte_size
  if storage_duration_of(dcl_or_def) == :static
    @memory_pool.allocate_static(byte_size)
  else
    @memory_pool.allocate_dynamic(byte_size)
  end
end
create_variable(dcl_or_def, type, mem) click to toggle source
# File lib/adlint/cc1/object.rb, line 870
def create_variable(dcl_or_def, type, mem)
  if dcl_or_def
    NamedVariable.new(mem, dcl_or_def, current_scope)
  else
    TemporaryVariable.new(mem, type, current_scope)
  end
end
current_scope() click to toggle source
# File lib/adlint/cc1/object.rb, line 878
def current_scope
  @scope_stack.last
end
define_variable(dcl_or_def, br, type, mem, init_val) click to toggle source
# File lib/adlint/cc1/object.rb, line 848
def define_variable(dcl_or_def, br, type, mem, init_val)
  var = create_variable(dcl_or_def, type, mem)
  var.assign!(init_val, dcl_or_def, br)

  if var.named?
    @named_variables.last[var.name] = var
  else
    @temp_variables.last.push(var)
  end

  var
end
rollback_all_global_variables_value!() click to toggle source
# File lib/adlint/cc1/object.rb, line 882
def rollback_all_global_variables_value!
  @named_variables.first.each_value do |var|
    # NOTE: Rollback effects recorded to global variables because execution
    #       of its accessors are out of order.
    var.rollback_all_value_versions!
  end
end