Exemple #1
0
def _skip_text_output_attribute():
    """Returns the IR for a [text_output: "Skip"] attribute."""
    result = ir_pb2.Attribute(name=ir_pb2.Word(text=attributes.TEXT_OUTPUT),
                              value=ir_pb2.AttributeValue(
                                  string_constant=ir_pb2.String(text="Skip")))
    _mark_as_synthetic(result)
    return result
Exemple #2
0
def _add_size_virtuals(structure, type_definition):
    """Adds a $size_in_bits or $size_in_bytes virtual field to structure."""
    names = {
        ir_pb2.TypeDefinition.BIT: "$size_in_bits",
        ir_pb2.TypeDefinition.BYTE: "$size_in_bytes",
    }
    size_field_name = names[type_definition.addressable_unit]
    size_clauses = []
    for field in structure.field:
        # Virtual fields do not have a physical location, and thus do not contribute
        # to the size of the structure.
        if ir_util.field_is_virtual(field):
            continue
        size_clause = ir_pb2.Expression()
        size_clause.CopyFrom(_SIZE_CLAUSE_SKELETON)
        # Copy the appropriate clauses into `existence_condition ? start + size : 0`
        size_clause.function.args[0].CopyFrom(field.existence_condition)
        size_clause.function.args[1].function.args[0].CopyFrom(
            field.location.start)
        size_clause.function.args[1].function.args[1].CopyFrom(
            field.location.size)
        size_clauses.append(size_clause)
    size_expression = ir_pb2.Expression()
    size_expression.CopyFrom(_SIZE_SKELETON)
    size_expression.function.args.extend(size_clauses)
    _mark_as_synthetic(size_expression)
    size_field = ir_pb2.Field(
        read_transform=size_expression,
        name=ir_pb2.NameDefinition(name=ir_pb2.Word(text=size_field_name)),
        existence_condition=ir_pb2.Expression(
            boolean_constant=ir_pb2.BooleanConstant(value=True)),
        attribute=[_skip_text_output_attribute()])
    structure.field.extend([size_field])
Exemple #3
0
 def test_get_duplicate_attribute(self):
     type_def = ir_pb2.TypeDefinition(attribute=[
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression()),
                          name=ir_pb2.Word(text="phil")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("true")),
                          name=ir_pb2.Word(text="bob")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("false")),
                          name=ir_pb2.Word(text="bob")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("false")),
                          name=ir_pb2.Word()),
     ])
     self.assertRaises(AssertionError, ir_util.get_attribute,
                       type_def.attribute, "bob")
Exemple #4
0
def _construct_string_attribute(name, value, source_location):
  """Constructs a string Attribute with the given name and value."""
  attr_value = ir_pb2.AttributeValue(
      string_constant=ir_pb2.String(text=value,
                                    source_location=source_location),
      source_location=source_location)
  return ir_pb2.Attribute(name=ir_pb2.Word(text=name,
                                           source_location=source_location),
                          value=attr_value,
                          source_location=source_location)
def _construct_boolean_attribute(name, value, source_location):
  """Constructs a boolean Attribute with the given name and value."""
  attr_value = ir_pb2.AttributeValue(
      expression=ir_pb2.Expression(
          boolean_constant=ir_pb2.BooleanConstant(
              value=value, source_location=source_location),
          type=ir_pb2.ExpressionType(boolean=ir_pb2.BooleanType(value=value)),
          source_location=source_location),
      source_location=source_location)
  return ir_pb2.Attribute(name=ir_pb2.Word(text=name,
                                           source_location=source_location),
                          value=attr_value,
                          source_location=source_location)
Exemple #6
0
def _add_size_bound_virtuals(structure, type_definition):
    """Adds ${min,max}_size_in_{bits,bytes} virtual fields to structure."""
    names = {
        ir_pb2.TypeDefinition.BIT: ("$max_size_in_bits", "$min_size_in_bits"),
        ir_pb2.TypeDefinition.BYTE:
        ("$max_size_in_bytes", "$min_size_in_bytes"),
    }
    for name in names[type_definition.addressable_unit]:
        bound_field = ir_pb2.Field(
            read_transform=_SIZE_BOUNDS[name],
            name=ir_pb2.NameDefinition(name=ir_pb2.Word(text=name)),
            existence_condition=expression_parser.parse("true"),
            attribute=[_skip_text_output_attribute()])
        _mark_as_synthetic(bound_field.read_transform)
        structure.field.extend([bound_field])
Exemple #7
0
def _construct_integer_attribute(name, value, source_location):
  """Constructs an integer Attribute with the given name and value."""
  attr_value = ir_pb2.AttributeValue(
      expression=ir_pb2.Expression(
          constant=ir_pb2.NumericConstant(value=str(value),
                                          source_location=source_location),
          type=ir_pb2.ExpressionType(
              integer=ir_pb2.IntegerType(modular_value=str(value),
                                         modulus="infinity",
                                         minimum_value=str(value),
                                         maximum_value=str(value))),
          source_location=source_location),
      source_location=source_location)
  return ir_pb2.Attribute(name=ir_pb2.Word(text=name),
                          value=attr_value,
                          source_location=source_location)
Exemple #8
0
def _add_struct_field_to_scope(field, scope, errors):
    """Adds the name of the given field to the scope."""
    new_scope = _add_name_to_scope_and_normalize(field.name, scope,
                                                 _Scope.LOCAL, errors)
    if field.HasField("abbreviation"):
        _add_name_to_scope(field.abbreviation, scope, new_scope.canonical_name,
                           _Scope.PRIVATE, errors)

    value_builtin_name = ir_pb2.Word(
        text="this",
        source_location=ir_pb2.Location(is_synthetic=True),
    )
    # In "inside field" scope, the name `this` maps back to the field itself.
    # This is important for attributes like `[requires]`.
    _add_name_to_scope(value_builtin_name, new_scope,
                       field.name.canonical_name, _Scope.PRIVATE, errors)
Exemple #9
0
 def test_get_boolean_attribute(self):
     type_def = ir_pb2.TypeDefinition(attribute=[
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression()),
                          name=ir_pb2.Word(text="phil")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("false")),
                          name=ir_pb2.Word(text="bob"),
                          is_default=True),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("true")),
                          name=ir_pb2.Word(text="bob")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("false")),
                          name=ir_pb2.Word(text="bob2")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("true")),
                          name=ir_pb2.Word(text="bob2"),
                          is_default=True),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("false")),
                          name=ir_pb2.Word(text="bob3"),
                          is_default=True),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=_parse_expression("false")),
                          name=ir_pb2.Word()),
     ])
     self.assertTrue(
         ir_util.get_boolean_attribute(type_def.attribute, "bob"))
     self.assertTrue(
         ir_util.get_boolean_attribute(type_def.attribute,
                                       "bob",
                                       default_value=False))
     self.assertFalse(
         ir_util.get_boolean_attribute(type_def.attribute, "bob2"))
     self.assertFalse(
         ir_util.get_boolean_attribute(type_def.attribute,
                                       "bob2",
                                       default_value=True))
     self.assertIsNone(
         ir_util.get_boolean_attribute(type_def.attribute, "Bob"))
     self.assertTrue(
         ir_util.get_boolean_attribute(type_def.attribute,
                                       "Bob",
                                       default_value=True))
     self.assertIsNone(
         ir_util.get_boolean_attribute(type_def.attribute, "bob3"))
Exemple #10
0
 def test_get_integer_attribute(self):
     type_def = ir_pb2.TypeDefinition(attribute=[
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(type=ir_pb2.ExpressionType(
                 integer=ir_pb2.IntegerType()))),
                          name=ir_pb2.Word(text="phil")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(
                 constant=ir_pb2.NumericConstant(value="20"),
                 type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType(
                     modular_value="20", modulus="infinity")))),
                          name=ir_pb2.Word(text="bob"),
                          is_default=True),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(
                 constant=ir_pb2.NumericConstant(value="10"),
                 type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType(
                     modular_value="10", modulus="infinity")))),
                          name=ir_pb2.Word(text="bob")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(
                 constant=ir_pb2.NumericConstant(value="5"),
                 type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType(
                     modular_value="5", modulus="infinity")))),
                          name=ir_pb2.Word(text="bob2")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(
                 constant=ir_pb2.NumericConstant(value="0"),
                 type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType(
                     modular_value="0", modulus="infinity")))),
                          name=ir_pb2.Word(text="bob2"),
                          is_default=True),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(
                 constant=ir_pb2.NumericConstant(value="30"),
                 type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType(
                     modular_value="30", modulus="infinity")))),
                          name=ir_pb2.Word(text="bob3"),
                          is_default=True),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(function=ir_pb2.Function(
                 function=ir_pb2.Function.ADDITION,
                 args=[
                     ir_pb2.Expression(
                         constant=ir_pb2.NumericConstant(value="100"),
                         type=ir_pb2.ExpressionType(
                             integer=ir_pb2.IntegerType(
                                 modular_value="100", modulus="infinity"))),
                     ir_pb2.Expression(
                         constant=ir_pb2.NumericConstant(value="100"),
                         type=ir_pb2.ExpressionType(
                             integer=ir_pb2.IntegerType(
                                 modular_value="100", modulus="infinity")))
                 ]),
                                          type=ir_pb2.ExpressionType(
                                              integer=ir_pb2.IntegerType(
                                                  modular_value="200",
                                                  modulus="infinity")))),
                          name=ir_pb2.Word(text="bob4")),
         ir_pb2.Attribute(value=ir_pb2.AttributeValue(
             expression=ir_pb2.Expression(
                 constant=ir_pb2.NumericConstant(value="40"),
                 type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType(
                     modular_value="40", modulus="infinity")))),
                          name=ir_pb2.Word()),
     ])
     self.assertEqual(
         10, ir_util.get_integer_attribute(type_def.attribute, "bob"))
     self.assertEqual(
         5, ir_util.get_integer_attribute(type_def.attribute, "bob2"))
     self.assertIsNone(
         ir_util.get_integer_attribute(type_def.attribute, "Bob"))
     self.assertEqual(
         10,
         ir_util.get_integer_attribute(type_def.attribute,
                                       "Bob",
                                       default_value=10))
     self.assertIsNone(
         ir_util.get_integer_attribute(type_def.attribute, "bob3"))
     self.assertEqual(
         200, ir_util.get_integer_attribute(type_def.attribute, "bob4"))
Exemple #11
0
def _invert_expression(expression, ir):
  """For the given expression, searches for an algebraic inverse expression.

  That is, it takes the notional equation:

      $logical_value = expression

  and, if there is exactly one `field_reference` in `expression`, it will
  attempt to solve the equation for that field.  For example, if the expression
  is `x + 1`, it will iteratively transform:

      $logical_value = x + 1
      $logical_value - 1 = x + 1 - 1
      $logical_value - 1 = x

  and finally return `x` and `$logical_value - 1`.

  The purpose of this transformation is to find an assignment statement that can
  be used to write back through certain virtual fields.  E.g., given:

      struct Foo:
        0 [+1]  UInt  raw_value
        let actual_value = raw_value + 100

  it should be possible to write a value to the `actual_value` field, and have
  it set `raw_value` to the appropriate value.

  Arguments:
    expression: an ir_pb2.Expression to be inverted.
    ir: the full IR, for looking up symbols.

  Returns:
    (field_reference, inverse_expression) if expression can be inverted,
    otherwise None.
  """
  reference_path = _find_field_reference_path(expression)
  if reference_path is None:
    return None
  subexpression = expression
  result = ir_pb2.Expression(
      builtin_reference=ir_pb2.Reference(
          canonical_name=ir_pb2.CanonicalName(
              module_file="",
              object_path=["$logical_value"]
          ),
          source_name=[ir_pb2.Word(
              text="$logical_value",
              source_location=ir_pb2.Location(is_synthetic=True)
          )],
          source_location=ir_pb2.Location(is_synthetic=True)
      ),
      type=expression.type,
      source_location=ir_pb2.Location(is_synthetic=True)
  )

  # This loop essentially starts with:
  #
  #     f(g(x)) == $logical_value
  #
  # and ends with
  #
  #     x == g_inv(f_inv($logical_value))
  #
  # At each step, `subexpression` has one layer removed, and `result` has a
  # corresponding inverse function applied.  So, for example, it might start
  # with:
  #
  #     2 + ((3 - x) - 10)  ==  $logical_value
  #
  # On each iteration, `subexpression` and `result` will become:
  #
  #     (3 - x) - 10  ==  $logical_value - 2    [subtract 2 from both sides]
  #     (3 - x)  ==  ($logical_value - 2) + 10  [add 10 to both sides]
  #     x  ==  3 - (($logical_value - 2) + 10)  [subtract both sides from 3]
  #
  # This is an extremely limited algebraic solver, but it covers common-enough
  # cases.
  #
  # Note that any equation that can be solved here becomes part of Emboss's
  # contract, forever, so be conservative in expanding its solving capabilities!
  for index in reference_path:
    if subexpression.function.function == ir_pb2.Function.ADDITION:
      result = ir_pb2.Expression(
          function=ir_pb2.Function(
              function=ir_pb2.Function.SUBTRACTION,
              args=[
                  result,
                  subexpression.function.args[1 - index],
              ]
          ),
          type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType())
      )
    elif subexpression.function.function == ir_pb2.Function.SUBTRACTION:
      if index == 0:
        result = ir_pb2.Expression(
            function=ir_pb2.Function(
                function=ir_pb2.Function.ADDITION,
                args=[
                    result,
                    subexpression.function.args[1],
                ]
            ),
            type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType())
        )
      else:
        result = ir_pb2.Expression(
            function=ir_pb2.Function(
                function=ir_pb2.Function.SUBTRACTION,
                args=[
                    subexpression.function.args[0],
                    result,
                ]
            ),
            type=ir_pb2.ExpressionType(integer=ir_pb2.IntegerType())
        )
    else:
      return None
    subexpression = subexpression.function.args[index]
  expression_bounds.compute_constraints_of_expression(result, ir)
  return subexpression, result