Example #1
0
void MCELFStreamer::EmitBundleUnlock() {
  MCSectionData *SD = getCurrentSectionData();

  // Sanity checks
  if (!getAssembler().isBundlingEnabled())
    report_fatal_error(".bundle_unlock forbidden when bundling is disabled");
  else if (!SD->isBundleLocked())
    report_fatal_error(".bundle_unlock without matching lock");
  else if (SD->isBundleGroupBeforeFirstInst())
    report_fatal_error("Empty bundle-locked group is forbidden");

  // When the -mc-relax-all flag is used, we emit instructions to fragments
  // stored on a stack. When the bundle unlock is emited, we pop a fragment 
  // from the stack a merge it to the one below.
  if (getAssembler().getRelaxAll()) {
    assert(!BundleGroups.empty() && "There are no bundle groups");
    MCDataFragment *DF = BundleGroups.back();

    // FIXME: Use BundleGroups to track the lock state instead.
    SD->setBundleLockState(MCSectionData::NotBundleLocked);

    // FIXME: Use more separate fragments for nested groups. 
    if (!SD->isBundleLocked()) {
      mergeFragment(getOrCreateDataFragment(), DF);
      BundleGroups.pop_back();
      delete DF;
    }

    if (SD->getBundleLockState() != MCSectionData::BundleLockedAlignToEnd)
      getOrCreateDataFragment()->setAlignToBundleEnd(false);
  } else
    SD->setBundleLockState(MCSectionData::NotBundleLocked);
}
void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
  MCAssembler &Assembler = getAssembler();
  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
  VecOS.flush();

  for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
    fixSymbolsInTLSFixups(Fixups[i].getValue());

  // There are several possibilities here:
  //
  // If bundling is disabled, append the encoded instruction to the current data
  // fragment (or create a new such fragment if the current fragment is not a
  // data fragment).
  //
  // If bundling is enabled:
  // - If we're not in a bundle-locked group, emit the instruction into a data
  //   fragment of its own.
  // - If we're in a bundle-locked group, append the instruction to the current
  //   data fragment because we want all the instructions in a group to get into
  //   the same fragment. Be careful not to do that for the first instruction in
  //   the group, though.
  MCDataFragment *DF;

  if (Assembler.isBundlingEnabled()) {
    MCSectionData *SD = getCurrentSectionData();
    if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
      DF = getOrCreateDataFragment();
    else {
      DF = new MCDataFragment(SD);
      if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
        // If this is a new fragment created for a bundle-locked group, and the
        // group was marked as "align_to_end", set a flag in the fragment.
        DF->setAlignToBundleEnd(true);
      }
    }

    // We're now emitting an instruction in a bundle group, so this flag has
    // to be turned off.
    SD->setBundleGroupBeforeFirstInst(false);
  } else {
    DF = getOrCreateDataFragment();
  }

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixups[i]);
  }
  DF->setHasInstructions(true);
  DF->getContents().append(Code.begin(), Code.end());
}
void MCELFStreamer::EmitInstToData(const MCInst &Inst,
                                   const MCSubtargetInfo &STI) {
  MCAssembler &Assembler = getAssembler();
  SmallVector<MCFixup, 4> Fixups;
  SmallString<256> Code;
  raw_svector_ostream VecOS(Code);
  Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI);
  VecOS.flush();

  for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
    fixSymbolsInTLSFixups(Fixups[i].getValue());

  // There are several possibilities here:
  //
  // If bundling is disabled, append the encoded instruction to the current data
  // fragment (or create a new such fragment if the current fragment is not a
  // data fragment).
  //
  // If bundling is enabled:
  // - If we're not in a bundle-locked group, emit the instruction into a
  //   fragment of its own. If there are no fixups registered for the
  //   instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a
  //   MCDataFragment.
  // - If we're in a bundle-locked group, append the instruction to the current
  //   data fragment because we want all the instructions in a group to get into
  //   the same fragment. Be careful not to do that for the first instruction in
  //   the group, though.
  MCDataFragment *DF;

  if (Assembler.isBundlingEnabled()) {
    MCSectionData *SD = getCurrentSectionData();
    if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
      // If we are bundle-locked, we re-use the current fragment.
      // The bundle-locking directive ensures this is a new data fragment.
      DF = cast<MCDataFragment>(getCurrentFragment());
    else if (!SD->isBundleLocked() && Fixups.size() == 0) {
      // Optimize memory usage by emitting the instruction to a
      // MCCompactEncodedInstFragment when not in a bundle-locked group and
      // there are no fixups registered.
      MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment();
      insert(CEIF);
      CEIF->getContents().append(Code.begin(), Code.end());
      return;
    } else {
      DF = new MCDataFragment();
      insert(DF);
    }
    if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
      // If this fragment is for a group marked "align_to_end", set a flag
      // in the fragment. This can happen after the fragment has already been
      // created if there are nested bundle_align groups and an inner one
      // is the one marked align_to_end.
      DF->setAlignToBundleEnd(true);
    }

    // We're now emitting an instruction in a bundle group, so this flag has
    // to be turned off.
    SD->setBundleGroupBeforeFirstInst(false);
  } else {
    DF = getOrCreateDataFragment();
  }

  // Add the fixups and data.
  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    DF->getFixups().push_back(Fixups[i]);
  }
  DF->setHasInstructions(true);
  DF->getContents().append(Code.begin(), Code.end());
}