Example #1
0
AliasClass AliasClass::operator|(AliasClass o) const {
  if (auto const c = precise_union(o)) return *c;

  auto const unioned = static_cast<rep>(m_bits | o.m_bits);

  // If they have the same stag, try to merge them with unionData.
  auto stag1 = m_stag;
  auto stag2 = o.m_stag;
  if (stag1 == stag2) return unionData(unioned, *this, o);

  // If one of the alias classes have a non-None stag, we can only keep it if
  // the other doesn't have the corresponding bit set.
  if (stag1 != STag::None && (o.m_bits & stagBit(stag1))) stag1 = STag::None;
  if (stag2 != STag::None && (m_bits & stagBit(stag2))) stag2 = STag::None;

  auto ret = AliasClass{unioned};
  if (stag1 == stag2) return ret;       // both None.

  // Note: union operations are guaranteed to be commutative, so if there are
  // two non-None stags, we have to consistently choose between them. For now
  // we keep the one with a smaller `rep' value, instead of discarding both.
  const AliasClass* chosen = &o;
  auto stag = stag2;
  if (stag1 != STag::None) {
    if (stag2 == STag::None || stagBit(stag1) < stagBit(stag2)) {
      chosen = this;
      stag = stag1;
    }
  }

  switch (stag) {
  case STag::None:
    break;
  case STag::Frame:   new (&ret.m_frame) AFrame(chosen->m_frame); break;
  case STag::Prop:    new (&ret.m_prop) AProp(chosen->m_prop); break;
  case STag::ElemI:   new (&ret.m_elemI) AElemI(chosen->m_elemI); break;
  case STag::ElemS:   new (&ret.m_elemS) AElemS(chosen->m_elemS); break;
  case STag::Stack:   new (&ret.m_stack) AStack(chosen->m_stack); break;
  case STag::MIState: new (&ret.m_mis) AMIState(chosen->m_mis); break;
  case STag::Ref:     new (&ret.m_ref) ARef(chosen->m_ref); break;
  }
  ret.m_stag = stag;
  return ret;
}
Example #2
0
AliasClass AliasClass::operator|(AliasClass o) const {
  if (o <= *this) return *this;
  if (*this <= o) return o;

  auto const unioned = static_cast<rep>(m_bits | o.m_bits);

  // Note: union operations are guaranteed to be commutative, so if there are
  // two non-None stags, we have to consistently choose between them.  For now
  // we throw both away in any case where they differ, and try to merge them
  // with unionData if they are the same.  If only one had an stag, we can keep
  // it only if the other didn't have that bit set.
  auto const stag1 = m_stag;
  auto const stag2 = o.m_stag;
  if (stag1 == stag2) return unionData(unioned, *this, o);
  if (stag1 != STag::None && stag2 != STag::None) {
    return AliasClass{unioned};
  }
  if (stag2 != STag::None) return o | *this;
  if (o.m_bits & stagBit(stag1)) {
    return AliasClass{unioned};
  }

  auto ret = AliasClass{unioned};
  switch (stag1) {
  case STag::None:
    break;
  case STag::Frame:   new (&ret.m_frame) AFrame(m_frame); break;
  case STag::Prop:    new (&ret.m_prop) AProp(m_prop); break;
  case STag::ElemI:   new (&ret.m_elemI) AElemI(m_elemI); break;
  case STag::ElemS:   new (&ret.m_elemS) AElemS(m_elemS); break;
  case STag::Stack:   new (&ret.m_stack) AStack(m_stack); break;
  case STag::MIState: new (&ret.m_mis) AMIState(m_mis); break;
  }
  ret.m_stag = stag1;
  return ret;
}