Class: AdLint::Cc1::VariableTable

Inherits:
Object
  • Object
show all
Defined in:
lib/adlint/cc1/object.rb

Instance Method Summary collapse

Constructor Details

#initialize(mem_pool) ⇒ VariableTable

Returns a new instance of VariableTable.



662
663
664
665
666
667
# File 'lib/adlint/cc1/object.rb', line 662

def initialize(mem_pool)
  @memory_pool     = mem_pool
  @named_variables = [{}]
  @temp_variables  = [[]]
  @scope_stack     = [GlobalScope.new]
end

Instance Method Details

#all_named_variablesObject



669
670
671
# File 'lib/adlint/cc1/object.rb', line 669

def all_named_variables
  @named_variables.map { |hash| hash.values }.flatten
end

#begin_variables_value_versioningObject



764
765
766
767
768
# File 'lib/adlint/cc1/object.rb', line 764

def begin_variables_value_versioning
  @named_variables.each do |hash|
    hash.each_value { |var| var.begin_value_versioning }
  end
end

#declare(dcl, br) ⇒ Object



691
692
693
694
695
696
697
698
699
700
# File 'lib/adlint/cc1/object.rb', line 691

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) ⇒ Object



702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
# File 'lib/adlint/cc1/object.rb', line 702

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) ⇒ Object



729
730
731
732
733
734
735
# File 'lib/adlint/cc1/object.rb', line 729

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

#designatorsObject



746
747
748
# File 'lib/adlint/cc1/object.rb', line 746

def designators
  @named_variables.map { |hash| hash.keys }.flatten.to_set
end

#end_variables_value_versioningObject



770
771
772
773
774
# File 'lib/adlint/cc1/object.rb', line 770

def end_variables_value_versioning
  @named_variables.each do |hash|
    hash.each_value { |var| var.end_value_versioning }
  end
end

#enter_scopeObject



673
674
675
676
677
# File 'lib/adlint/cc1/object.rb', line 673

def enter_scope
  @named_variables.push({})
  @temp_variables.push([])
  @scope_stack.push(Scope.new(@scope_stack.size))
end

#enter_variables_value_versioning_groupObject



750
751
752
753
754
# File 'lib/adlint/cc1/object.rb', line 750

def enter_variables_value_versioning_group
  @named_variables.each do |hash|
    hash.each_value { |var| var.enter_value_versioning_group }
  end
end

#leave_scopeObject



679
680
681
682
683
684
685
686
687
688
689
# File 'lib/adlint/cc1/object.rb', line 679

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) ⇒ Object



756
757
758
759
760
761
762
# File 'lib/adlint/cc1/object.rb', line 756

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) ⇒ Object



737
738
739
740
741
742
743
744
# File 'lib/adlint/cc1/object.rb', line 737

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) ⇒ Object



782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
# File 'lib/adlint/cc1/object.rb', line 782

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) ⇒ Object



776
777
778
779
780
# File 'lib/adlint/cc1/object.rb', line 776

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