/// Emit extern decls for functions imported from other modules, and emit
/// global declarations for function defined in this module and which are
/// available to other modules.
///
void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
 // Emit declarations for external functions.
  O <<"\n"<<MAI->getCommentString() << "Function Declarations - BEGIN." <<"\n";
  for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
    if (I->isIntrinsic() || I->getName() == "@abort")
      continue;
    
    if (!I->isDeclaration() && !I->hasExternalLinkage())
      continue;

    MCSymbol *Sym = Mang->getSymbol(I);
    
    // Do not emit memcpy, memset, and memmove here.
    // Calls to these routines can be generated in two ways,
    // 1. User calling the standard lib function
    // 2. Codegen generating these calls for llvm intrinsics.
    // In the first case a prototype is alread availale, while in
    // second case the call is via and externalsym and the prototype is missing.
    // So declarations for these are currently always getting printing by
    // tracking both kind of references in printInstrunction.
    if (I->isDeclaration() && PAN::isMemIntrinsic(Sym->getName())) continue;

    const char *directive = I->isDeclaration() ? MAI->getExternDirective() :
                                                 MAI->getGlobalDirective();
      
    O << directive << Sym->getName() << "\n";
    O << directive << PAN::getRetvalLabel(Sym->getName()) << "\n";
    O << directive << PAN::getArgsLabel(Sym->getName()) << "\n";
  }

  O << MAI->getCommentString() << "Function Declarations - END." <<"\n";
}
const MCSection *TargetLoweringObjectFileCOFF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
                       Mangler *Mang, const TargetMachine &TM) const {

  // If this global is linkonce/weak and the target handles this by emitting it
  // into a 'uniqued' section name, create and return the section now.
  if (GV->isWeakForLinker()) {
    const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind);
    SmallString<128> Name(Prefix, Prefix+strlen(Prefix));
    MCSymbol *Sym = Mang->getSymbol(GV);
    Name.append(Sym->getName().begin() + 1, Sym->getName().end());

    unsigned Characteristics = getCOFFSectionFlags(Kind);

    Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;

    return getContext().getCOFFSection(Name.str(), Characteristics,
                          COFF::IMAGE_COMDAT_SELECT_ANY, Kind);
  }

  if (Kind.isText())
    return getTextSection();

  if (Kind.isThreadLocal())
    return getTLSDataSection();

  return getDataSection();
}
void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
  // Check to see if this is a special global used by LLVM, if so, emit it.
  if (!GV->hasInitializer() ||
      EmitSpecialLLVMGlobal(GV))
    return;

  const DataLayout *TD = TM.getDataLayout();
  OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));

  
  MCSymbol *GVSym = getSymbol(GV);
  const Constant *C = GV->getInitializer();
  unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
  
  // Mark the start of the global
  getTargetStreamer().emitCCTopData(GVSym->getName());

  switch (GV->getLinkage()) {
  case GlobalValue::AppendingLinkage:
    report_fatal_error("AppendingLinkage is not supported by this target!");
  case GlobalValue::LinkOnceAnyLinkage:
  case GlobalValue::LinkOnceODRLinkage:
  case GlobalValue::WeakAnyLinkage:
  case GlobalValue::WeakODRLinkage:
  case GlobalValue::ExternalLinkage:
    emitArrayBound(GVSym, GV);
    OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);

    // TODO Use COMDAT groups for LinkOnceLinkage
    if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
      OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
    // FALL THROUGH
  case GlobalValue::InternalLinkage:
  case GlobalValue::PrivateLinkage:
    break;
  default:
    llvm_unreachable("Unknown linkage type!");
  }

  EmitAlignment(Align > 2 ? Align : 2, GV);
  
  if (GV->isThreadLocal()) {
    report_fatal_error("TLS is not supported by this target!");
  }
  unsigned Size = TD->getTypeAllocSize(C->getType());
  if (MAI->hasDotTypeDotSizeDirective()) {
    OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
    OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext));
  }
  OutStreamer.EmitLabel(GVSym);
  
  EmitGlobalConstant(C);
  // The ABI requires that unsigned scalar types smaller than 32 bits
  // are padded to 32 bits.
  if (Size < 4)
    OutStreamer.EmitZeros(4 - Size);
  
  // Mark the end of the global
  getTargetStreamer().emitCCBottomData(GVSym->getName());
}
// printOperand - print operand of insn.
void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
  const MachineOperand &MO = MI->getOperand(opNum);
  const Function *F = MI->getParent()->getParent()->getFunction();

  switch (MO.getType()) {
    case MachineOperand::MO_Register:
      {
        // For indirect load/store insns, the fsr name is printed as INDF.
        std::string RegName = getRegisterName(MO.getReg());
        if ((MI->getOpcode() == PIC16::load_indirect) ||
            (MI->getOpcode() == PIC16::store_indirect))
        {
          RegName.replace (0, 3, "INDF");
        }
        O << RegName;
      }
      return;

    case MachineOperand::MO_Immediate:
      O << (int)MO.getImm();
      return;

    case MachineOperand::MO_GlobalAddress: {
      MCSymbol *Sym = Mang->getSymbol(MO.getGlobal());
      // FIXME: currently we do not have a memcpy def coming in the module
      // by any chance, as we do not link in those as .bc lib. So these calls
      // are always external and it is safe to emit an extern.
      if (PAN::isMemIntrinsic(Sym->getName()))
        LibcallDecls.push_back(createESName(Sym->getName()));

      O << *Sym;
      break;
    }
    case MachineOperand::MO_ExternalSymbol: {
       const char *Sname = MO.getSymbolName();
       std::string Printname = Sname;

      // Intrinsic stuff needs to be renamed if we are printing IL fn. 
      if (PAN::isIntrinsicStuff(Printname)) {
        if (PAN::isISR(F->getSection())) {
          Printname = PAN::Rename(Sname);
        }
        // Record these decls, we need to print them in asm as extern.
        LibcallDecls.push_back(createESName(Printname));
      }

      O << Printname;
      break;
    }
    case MachineOperand::MO_MachineBasicBlock:
      O << *MO.getMBB()->getSymbol();
      return;

    default:
      llvm_unreachable(" Operand type not supported.");
  }
}
/// This hook allows targets to selectively decide not to emit the UsedDirective
/// for some symbols in llvm.used.
// FIXME: REMOVE this (rdar://7071300)
bool TargetLoweringObjectFileMachO::shouldEmitUsedDirectiveFor(
    const GlobalValue *GV, Mangler &Mang, TargetMachine &TM) const {
  // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix.
  if (GV->hasLocalLinkage() && !isa<Function>(GV)) {
    // FIXME: ObjC metadata is currently emitted as internal symbols that have
    // \1L and \0l prefixes on them.  Fix them to be Private/LinkerPrivate and
    // this horrible hack can go away.
    MCSymbol *Sym = TM.getSymbol(GV, Mang);
    if (Sym->getName()[0] == 'L' || Sym->getName()[0] == 'l')
      return false;
  }

  return true;
}
const MCSection *TargetLoweringObjectFileCOFF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
                       Mangler &Mang, const TargetMachine &TM) const {

  // If this global is linkonce/weak and the target handles this by emitting it
  // into a 'uniqued' section name, create and return the section now.
  if (GV->isWeakForLinker()) {
    const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
    unsigned Characteristics = getCOFFSectionFlags(Kind);

    Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    MCSymbol *Sym = TM.getSymbol(GV, Mang);
    return getContext().getCOFFSection(Name, Characteristics,
                                       Kind, Sym->getName(),
                                       COFF::IMAGE_COMDAT_SELECT_ANY);
  }

  if (Kind.isText())
    return TextSection;

  if (Kind.isThreadLocal())
    return TLSDataSection;

  if (Kind.isReadOnly())
    return ReadOnlySection;

  if (Kind.isBSS())
    return BSSSection;

  return DataSection;
}
Example #7
0
uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S,
                                            const MCAsmLayout &Layout) const {
  // If this is a variable, then recursively evaluate now.
  if (S.isVariable()) {
    if (const MCConstantExpr *C =
          dyn_cast<const MCConstantExpr>(S.getVariableValue()))
      return C->getValue();

    MCValue Target;
    if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Layout, nullptr))
      report_fatal_error("unable to evaluate offset for variable '" +
                         S.getName() + "'");

    // Verify that any used symbols are defined.
    if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined())
      report_fatal_error("unable to evaluate offset to undefined symbol '" +
                         Target.getSymA()->getSymbol().getName() + "'");
    if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined())
      report_fatal_error("unable to evaluate offset to undefined symbol '" +
                         Target.getSymB()->getSymbol().getName() + "'");

    uint64_t Address = Target.getConstant();
    if (Target.getSymA())
      Address += getSymbolAddress(Target.getSymA()->getSymbol(), Layout);
    if (Target.getSymB())
      Address += getSymbolAddress(Target.getSymB()->getSymbol(), Layout);
    return Address;
  }

  return getSectionAddress(S.getFragment()->getParent()) +
         Layout.getSymbolOffset(S);
}
void TargetLoweringObjectFileELF::emitPersonalityValue(MCStreamer &Streamer,
                                                       const TargetMachine &TM,
                                                       const MCSymbol *Sym) const {
  SmallString<64> NameData("DW.ref.");
  NameData += Sym->getName();
  MCSymbol *Label = getContext().GetOrCreateSymbol(NameData);
  Streamer.EmitSymbolAttribute(Label, MCSA_Hidden);
  Streamer.EmitSymbolAttribute(Label, MCSA_Weak);
  StringRef Prefix = ".data.";
  NameData.insert(NameData.begin(), Prefix.begin(), Prefix.end());
  unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP;
  const MCSection *Sec = getContext().getELFSection(NameData,
                                                    ELF::SHT_PROGBITS,
                                                    Flags,
                                                    SectionKind::getDataRel(),
                                                    0, Label->getName());
  unsigned Size = TM.getDataLayout()->getPointerSize(0);
  Streamer.SwitchSection(Sec);
  Streamer.EmitValueToAlignment(TM.getDataLayout()->getPointerABIAlignment(0));
  Streamer.EmitSymbolAttribute(Label, MCSA_ELF_TypeObject);
  const MCExpr *E = MCConstantExpr::Create(Size, getContext());
  Streamer.EmitELFSize(Label, E);
  Streamer.EmitLabel(Label);

  Streamer.EmitSymbolValue(Sym, Size);
}
const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
    const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM) const {
  int Selection = 0;
  unsigned Characteristics = getCOFFSectionFlags(Kind);
  StringRef Name = GV->getSection();
  StringRef COMDATSymName = "";
  if ((GV->isWeakForLinker() || GV->hasComdat()) && !Kind.isCommon()) {
    Selection = getSelectionForCOFF(GV);
    const GlobalValue *ComdatGV;
    if (Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
      ComdatGV = getComdatGVForCOFF(GV);
    else
      ComdatGV = GV;

    if (!ComdatGV->hasPrivateLinkage()) {
      MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang);
      COMDATSymName = Sym->getName();
      Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    } else {
      Selection = 0;
    }
  }
  return getContext().getCOFFSection(Name,
                                     Characteristics,
                                     Kind,
                                     COMDATSymName,
                                     Selection);
}
Example #10
0
static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S,
                                bool ReportError, uint64_t &Val) {
  if (!S.isVariable())
    return getLabelOffset(Layout, S, ReportError, Val);

  // If SD is a variable, evaluate it.
  MCValue Target;
  if (!S.getVariableValue()->evaluateAsValue(Target, Layout))
    report_fatal_error("unable to evaluate offset for variable '" +
                       S.getName() + "'");

  uint64_t Offset = Target.getConstant();

  const MCSymbolRefExpr *A = Target.getSymA();
  if (A) {
    uint64_t ValA;
    if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA))
      return false;
    Offset += ValA;
  }

  const MCSymbolRefExpr *B = Target.getSymB();
  if (B) {
    uint64_t ValB;
    if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB))
      return false;
    Offset -= ValB;
  }

  Val = Offset;
  return true;
}
void TargetLoweringObjectFileELF::emitPersonalityValue(MCStreamer &Streamer,
                                                       const TargetMachine &TM,
                                                       const MCSymbol *Sym) const {
  SmallString<64> NameData("DW.ref.");
  // @LOCALMOD-BEGIN
  // The dwarf section label should not include the version suffix.
  // Strip it off here.
  StringRef Name = Sym->getName();
  size_t atpos = Name.find("@");
  if (atpos != StringRef::npos)
    Name = Name.substr(0, atpos);
  // @LOCALMOD-END
  NameData += Name; // @LOCALMOD
  MCSymbol *Label = getContext().GetOrCreateSymbol(NameData);
  Streamer.EmitSymbolAttribute(Label, MCSA_Hidden);
  Streamer.EmitSymbolAttribute(Label, MCSA_Weak);
  StringRef Prefix = ".data.";
  NameData.insert(NameData.begin(), Prefix.begin(), Prefix.end());
  unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP;
  const MCSection *Sec = getContext().getELFSection(NameData,
                                                    ELF::SHT_PROGBITS,
                                                    Flags,
                                                    SectionKind::getDataRel(),
                                                    0, Label->getName());
  unsigned Size = TM.getDataLayout()->getPointerSize();
  Streamer.SwitchSection(Sec);
  Streamer.EmitValueToAlignment(TM.getDataLayout()->getPointerABIAlignment());
  Streamer.EmitSymbolAttribute(Label, MCSA_ELF_TypeObject);
  const MCExpr *E = MCConstantExpr::Create(Size, getContext());
  Streamer.EmitELFSize(Label, E);
  Streamer.EmitLabel(Label);

  Streamer.EmitSymbolValue(Sym, Size);
}
MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable(
    const Function &F, const TargetMachine &TM) const {
  // If the function can be removed, produce a unique section so that
  // the table doesn't prevent the removal.
  const Comdat *C = F.getComdat();
  bool EmitUniqueSection = TM.getFunctionSections() || C;
  if (!EmitUniqueSection)
    return ReadOnlySection;

  // FIXME: we should produce a symbol for F instead.
  if (F.hasPrivateLinkage())
    return ReadOnlySection;

  MCSymbol *Sym = TM.getSymbol(&F);
  StringRef COMDATSymName = Sym->getName();

  SectionKind Kind = SectionKind::getReadOnly();
  const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
  unsigned Characteristics = getCOFFSectionFlags(Kind, TM);
  Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
  unsigned UniqueID = NextUniqueID++;

  return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName,
                                     COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
}
Example #13
0
MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
                                         unsigned Characteristics,
                                         SectionKind Kind,
                                         StringRef COMDATSymName, int Selection,
                                         const char *BeginSymName) {
  MCSymbol *COMDATSymbol = nullptr;
  if (!COMDATSymName.empty()) {
    COMDATSymbol = getOrCreateSymbol(COMDATSymName);
    COMDATSymName = COMDATSymbol->getName();
  }

  // Do the lookup, if we have a hit, return it.
  COFFSectionKey T{Section, COMDATSymName, Selection};
  auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr));
  auto Iter = IterBool.first;
  if (!IterBool.second)
    return Iter->second;

  MCSymbol *Begin = nullptr;
  if (BeginSymName)
    Begin = createTempSymbol(BeginSymName, false);

  StringRef CachedName = Iter->first.SectionName;
  MCSectionCOFF *Result = new (COFFAllocator.Allocate()) MCSectionCOFF(
      CachedName, Characteristics, COMDATSymbol, Selection, Kind, Begin);

  Iter->second = Result;
  return Result;
}
MCSection *TargetLoweringObjectFileCOFF::SelectSectionForGlobal(
    const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM) const {
  // If we have -ffunction-sections then we should emit the global value to a
  // uniqued section specifically for it.
  bool EmitUniquedSection;
  if (Kind.isText())
    EmitUniquedSection = TM.getFunctionSections();
  else
    EmitUniquedSection = TM.getDataSections();

  if ((EmitUniquedSection && !Kind.isCommon()) || GV->hasComdat()) {
    const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
    unsigned Characteristics = getCOFFSectionFlags(Kind);

    Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    int Selection = getSelectionForCOFF(GV);
    if (!Selection)
      Selection = COFF::IMAGE_COMDAT_SELECT_NODUPLICATES;
    const GlobalValue *ComdatGV;
    if (GV->hasComdat())
      ComdatGV = getComdatGVForCOFF(GV);
    else
      ComdatGV = GV;

    unsigned UniqueID = MCContext::GenericSectionID;
    if (EmitUniquedSection)
      UniqueID = NextUniqueID++;

    if (!ComdatGV->hasPrivateLinkage()) {
      MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang);
      StringRef COMDATSymName = Sym->getName();
      return getContext().getCOFFSection(Name, Characteristics, Kind,
                                         COMDATSymName, Selection, UniqueID);
    } else {
      SmallString<256> TmpData;
      Mang.getNameWithPrefix(TmpData, GV, /*CannotUsePrivateLabel=*/true);
      return getContext().getCOFFSection(Name, Characteristics, Kind, TmpData,
                                         Selection, UniqueID);
    }
  }

  if (Kind.isText())
    return TextSection;

  if (Kind.isThreadLocal())
    return TLSDataSection;

  if (Kind.isReadOnly() || Kind.isReadOnlyWithRel())
    return ReadOnlySection;

  // Note: we claim that common symbols are put in BSSSection, but they are
  // really emitted with the magic .comm directive, which creates a symbol table
  // entry but not a section.
  if (Kind.isBSS() || Kind.isCommon())
    return BSSSection;

  return DataSection;
}
Example #15
0
const MCSection *TargetLoweringObjectFileCOFF::
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
                         Mangler *Mang, const TargetMachine &TM) const {
  int Selection = 0;
  unsigned Characteristics = getCOFFSectionFlags(Kind);
  SmallString<128> Name(GV->getSection().c_str());
  if (GV->isWeakForLinker()) {
    Selection = COFF::IMAGE_COMDAT_SELECT_ANY;
    Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    MCSymbol *Sym = Mang->getSymbol(GV);
    Name.append("$");
    Name.append(Sym->getName().begin() + 1, Sym->getName().end());
  }
  return getContext().getCOFFSection(Name,
                                     Characteristics,
                                     Selection,
                                     Kind);
}
/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide
/// not to emit the UsedDirective for some symbols in llvm.used.
// FIXME: REMOVE this (rdar://7071300)
bool TargetLoweringObjectFileMachO::
shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const {
  /// On Darwin, internally linked data beginning with "L" or "l" does not have
  /// the directive emitted (this occurs in ObjC metadata).
  if (!GV) return false;

  // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix.
  if (GV->hasLocalLinkage() && !isa<Function>(GV)) {
    // FIXME: ObjC metadata is currently emitted as internal symbols that have
    // \1L and \0l prefixes on them.  Fix them to be Private/LinkerPrivate and
    // this horrible hack can go away.
    MCSymbol *Sym = Mang->getSymbol(GV);
    if (Sym->getName()[0] == 'L' || Sym->getName()[0] == 'l')
      return false;
  }

  return true;
}
const MCSection *TargetLoweringObjectFileCOFF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
                       Mangler &Mang, const TargetMachine &TM) const {
  // If we have -ffunction-sections then we should emit the global value to a
  // uniqued section specifically for it.
  bool EmitUniquedSection;
  if (Kind.isText())
    EmitUniquedSection = TM.getFunctionSections();
  else
    EmitUniquedSection = TM.getDataSections();

  // If this global is linkonce/weak and the target handles this by emitting it
  // into a 'uniqued' section name, create and return the section now.
  // Section names depend on the name of the symbol which is not feasible if the
  // symbol has private linkage.
  if ((GV->isWeakForLinker() || EmitUniquedSection || GV->hasComdat()) &&
      !Kind.isCommon()) {
    const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
    unsigned Characteristics = getCOFFSectionFlags(Kind);

    Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    int Selection = getSelectionForCOFF(GV);
    if (!Selection)
      Selection = COFF::IMAGE_COMDAT_SELECT_NODUPLICATES;
    const GlobalValue *ComdatGV;
    if (GV->hasComdat())
      ComdatGV = getComdatGVForCOFF(GV);
    else
      ComdatGV = GV;

    if (!ComdatGV->hasPrivateLinkage()) {
      MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang);
      StringRef COMDATSymName = Sym->getName();
      return getContext().getCOFFSection(Name, Characteristics, Kind,
                                         COMDATSymName, Selection);
    }
  }

  if (Kind.isText())
    return TextSection;

  if (Kind.isThreadLocal())
    return TLSDataSection;

  if (Kind.isReadOnly())
    return ReadOnlySection;

  // Note: we claim that common symbols are put in BSSSection, but they are
  // really emitted with the magic .comm directive, which creates a symbol table
  // entry but not a section.
  if (Kind.isBSS() || Kind.isCommon())
    return BSSSection;

  return DataSection;
}
Example #18
0
// Simple getSymbolOffset helper for the non-varibale case.
static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S,
                           bool ReportError, uint64_t &Val) {
  if (!S.getFragment()) {
    if (ReportError)
      report_fatal_error("unable to evaluate offset to undefined symbol '" +
                         S.getName() + "'");
    return false;
  }
  Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset();
  return true;
}
Example #19
0
void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
                                   raw_ostream &O, const char *Modifier) {
  const MachineOperand &MO = MI->getOperand(OpNum);
  unsigned TF = MO.getTargetFlags();

  switch (MO.getType()) {
  case MachineOperand::MO_Register:
    O << LanaiInstPrinter::getRegisterName(MO.getReg());
    break;

  case MachineOperand::MO_Immediate:
    O << MO.getImm();
    break;

  case MachineOperand::MO_MachineBasicBlock:
    O << *MO.getMBB()->getSymbol();
    break;

  case MachineOperand::MO_GlobalAddress:
    if (TF == LanaiII::MO_PLT)
      O << "plt(" << *getSymbol(MO.getGlobal()) << ")";
    else
      O << *getSymbol(MO.getGlobal());
    break;

  case MachineOperand::MO_BlockAddress: {
    MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
    O << BA->getName();
    break;
  }

  case MachineOperand::MO_ExternalSymbol:
    if (TF == LanaiII::MO_PLT)
      O << "plt(" << *GetExternalSymbolSymbol(MO.getSymbolName()) << ")";
    else
      O << *GetExternalSymbolSymbol(MO.getSymbolName());
    break;

  case MachineOperand::MO_JumpTableIndex:
    O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
      << MO.getIndex();
    break;

  case MachineOperand::MO_ConstantPoolIndex:
    O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
      << MO.getIndex();
    return;

  default:
    llvm_unreachable("<unknown operand type>");
  }
}
Example #20
0
void RecordStreamer::markUsed(const MCSymbol &Symbol) {
  State &S = Symbols[Symbol.getName()];
  switch (S) {
  case DefinedGlobal:
  case Defined:
  case Global:
  case DefinedWeak:
  case UndefinedWeak:
    break;

  case NeverSeen:
  case Used:
    S = Used;
    break;
  }
}
const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
    const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM) const {
  int Selection = 0;
  unsigned Characteristics = getCOFFSectionFlags(Kind);
  StringRef Name = GV->getSection();
  StringRef COMDATSymName = "";
  if (GV->isWeakForLinker()) {
    Selection = COFF::IMAGE_COMDAT_SELECT_ANY;
    Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    MCSymbol *Sym = TM.getSymbol(GV, Mang);
    COMDATSymName = Sym->getName();
  }
  return getContext().getCOFFSection(Name,
                                     Characteristics,
                                     Kind,
                                     COMDATSymName,
                                     Selection);
}
Example #22
0
void RecordStreamer::markGlobal(const MCSymbol &Symbol,
                                MCSymbolAttr Attribute) {
  State &S = Symbols[Symbol.getName()];
  switch (S) {
  case DefinedGlobal:
  case Defined:
    S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal;
    break;

  case NeverSeen:
  case Global:
  case Used:
    S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global;
    break;
  case UndefinedWeak:
  case DefinedWeak:
    break;
  }
}
Example #23
0
void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable *gv) {
  // Check to see if this is a special global used by LLVM, if so, emit it.
  if (EmitSpecialLLVMGlobal(gv))
    return;

  MCSymbol *gvsym = Mang->getSymbol(gv);

  assert(gvsym->isUndefined() && "Cannot define a symbol twice!");

  std::string decl;

  // check if it is defined in some other translation unit
  if (gv->isDeclaration())
    decl += ".extern ";

  // state space: e.g., .global
  decl += ".";
  decl += getStateSpaceName(gv->getType()->getAddressSpace());
  decl += " ";

  // alignment (optional)
  unsigned alignment = gv->getAlignment();
  if (alignment != 0) {
    decl += ".align ";
    decl += utostr(Log2_32(gv->getAlignment()));
    decl += " ";
  }

  // TODO: add types
  decl += ".s32 ";

  decl += gvsym->getName();

  if (ArrayType::classof(gv->getType()) || PointerType::classof(gv->getType()))
    decl += "[]";

  decl += ";";

  OutStreamer.EmitRawText(Twine(decl));

  OutStreamer.AddBlankLine();
}
Example #24
0
static MCSymbol *smallData(AsmPrinter &AP, const MachineInstr &MI,
                           MCStreamer &OutStreamer, const MCOperand &Imm,
                           int AlignSize) {
  MCSymbol *Sym;
  int64_t Value;
  if (Imm.getExpr()->evaluateAsAbsolute(Value)) {
    StringRef sectionPrefix;
    std::string ImmString;
    StringRef Name;
    if (AlignSize == 8) {
       Name = ".CONST_0000000000000000";
       sectionPrefix = ".gnu.linkonce.l8";
       ImmString = utohexstr(Value);
    } else {
       Name = ".CONST_00000000";
       sectionPrefix = ".gnu.linkonce.l4";
       ImmString = utohexstr(static_cast<uint32_t>(Value));
    }

    std::string symbolName =   // Yes, leading zeros are kept.
      Name.drop_back(ImmString.size()).str() + ImmString;
    std::string sectionName = sectionPrefix.str() + symbolName;

    MCSectionELF *Section = OutStreamer.getContext().getELFSection(
        sectionName, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
    OutStreamer.SwitchSection(Section);

    Sym = AP.OutContext.getOrCreateSymbol(Twine(symbolName));
    if (Sym->isUndefined()) {
      OutStreamer.EmitLabel(Sym);
      OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global);
      OutStreamer.EmitIntValue(Value, AlignSize);
      OutStreamer.EmitCodeAlignment(AlignSize);
    }
  } else {
    assert(Imm.isExpr() && "Expected expression and found none");
    const MachineOperand &MO = MI.getOperand(1);
    assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
    MCSymbol *MOSymbol = nullptr;
    if (MO.isGlobal())
      MOSymbol = AP.getSymbol(MO.getGlobal());
    else if (MO.isCPI())
      MOSymbol = AP.GetCPISymbol(MO.getIndex());
    else if (MO.isJTI())
      MOSymbol = AP.GetJTISymbol(MO.getIndex());
    else
      llvm_unreachable("Unknown operand type!");

    StringRef SymbolName = MOSymbol->getName();
    std::string LitaName = ".CONST_" + SymbolName.str();

    MCSectionELF *Section = OutStreamer.getContext().getELFSection(
        ".lita", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);

    OutStreamer.SwitchSection(Section);
    Sym = AP.OutContext.getOrCreateSymbol(Twine(LitaName));
    if (Sym->isUndefined()) {
      OutStreamer.EmitLabel(Sym);
      OutStreamer.EmitSymbolAttribute(Sym, MCSA_Local);
      OutStreamer.EmitValue(Imm.getExpr(), AlignSize);
      OutStreamer.EmitCodeAlignment(AlignSize);
    }
  }
  return Sym;
}
Example #25
0
void PPCDarwinAsmPrinter::
EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) {
  bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64;
  
  const TargetLoweringObjectFileMachO &TLOFMacho = 
    static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());

  // .lazy_symbol_pointer
  const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection();
  
  // Output stubs for dynamically-linked functions
  if (TM.getRelocationModel() == Reloc::PIC_) {
    const MCSection *StubSection = 
    OutContext.getMachOSection("__TEXT", "__picsymbolstub1",
                               MCSectionMachO::S_SYMBOL_STUBS |
                               MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
                               32, SectionKind::getText());
    for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
      OutStreamer.SwitchSection(StubSection);
      EmitAlignment(4);
      
      MCSymbol *Stub = Stubs[i].first;
      MCSymbol *RawSym = Stubs[i].second.getPointer();
      MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);
      MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext);
                                           
      OutStreamer.EmitLabel(Stub);
      OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
      // FIXME: MCize this.
      OutStreamer.EmitRawText(StringRef("\tmflr r0"));
      OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName()));
      OutStreamer.EmitLabel(AnonSymbol);
      OutStreamer.EmitRawText(StringRef("\tmflr r11"));
      OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+
                              "-" + AnonSymbol->getName() + ")");
      OutStreamer.EmitRawText(StringRef("\tmtlr r0"));
      
      if (isPPC64)
        OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) +
                                "-" + AnonSymbol->getName() + ")(r11)");
      else
        OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) +
                                "-" + AnonSymbol->getName() + ")(r11)");
      OutStreamer.EmitRawText(StringRef("\tmtctr r12"));
      OutStreamer.EmitRawText(StringRef("\tbctr"));
      
      OutStreamer.SwitchSection(LSPSection);
      OutStreamer.EmitLabel(LazyPtr);
      OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
      
      if (isPPC64)
        OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper"));
      else
        OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper"));
    }
    OutStreamer.AddBlankLine();
    return;
  }
  
  const MCSection *StubSection =
    OutContext.getMachOSection("__TEXT","__symbol_stub1",
                               MCSectionMachO::S_SYMBOL_STUBS |
                               MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
                               16, SectionKind::getText());
  for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
    MCSymbol *Stub = Stubs[i].first;
    MCSymbol *RawSym = Stubs[i].second.getPointer();
    MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext);

    OutStreamer.SwitchSection(StubSection);
    EmitAlignment(4);
    OutStreamer.EmitLabel(Stub);
    OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
    OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")");
    if (isPPC64)
      OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) +
                              ")(r11)");
    else
      OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) +
                              ")(r11)");
    OutStreamer.EmitRawText(StringRef("\tmtctr r12"));
    OutStreamer.EmitRawText(StringRef("\tbctr"));
    OutStreamer.SwitchSection(LSPSection);
    OutStreamer.EmitLabel(LazyPtr);
    OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol);
    
    if (isPPC64)
      OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper"));
    else
      OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper"));
  }
  
  OutStreamer.AddBlankLine();
}
Example #26
0
void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
                                  raw_ostream &O) {
  const MachineOperand &MO = MI->getOperand(opNum);
  bool closeP = false;

  if (MO.getTargetFlags())
    closeP = true;

  switch(MO.getTargetFlags()) {
  case MipsII::MO_GPREL:    O << "%gp_rel("; break;
  case MipsII::MO_GOT_CALL: O << "%call16("; break;
  case MipsII::MO_GOT:      O << "%got(";    break;
  case MipsII::MO_ABS_HI:   O << "%hi(";     break;
  case MipsII::MO_ABS_LO:   O << "%lo(";     break;
  case MipsII::MO_TLSGD:    O << "%tlsgd(";  break;
  case MipsII::MO_GOTTPREL: O << "%gottprel("; break;
  case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break;
  case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break;
  case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break;
  case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break;
  case MipsII::MO_GOT_DISP: O << "%got_disp("; break;
  case MipsII::MO_GOT_PAGE: O << "%got_page("; break;
  case MipsII::MO_GOT_OFST: O << "%got_ofst("; break;
  }

  switch (MO.getType()) {
    case MachineOperand::MO_Register:
      O << '$'
        << StringRef(MipsInstPrinter::getRegisterName(MO.getReg())).lower();
      break;

    case MachineOperand::MO_Immediate:
      O << MO.getImm();
      break;

    case MachineOperand::MO_MachineBasicBlock:
      MO.getMBB()->getSymbol()->print(O, MAI);
      return;

    case MachineOperand::MO_GlobalAddress:
      getSymbol(MO.getGlobal())->print(O, MAI);
      break;

    case MachineOperand::MO_BlockAddress: {
      MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
      O << BA->getName();
      break;
    }

    case MachineOperand::MO_ConstantPoolIndex:
      O << getDataLayout().getPrivateGlobalPrefix() << "CPI"
        << getFunctionNumber() << "_" << MO.getIndex();
      if (MO.getOffset())
        O << "+" << MO.getOffset();
      break;

    default:
      llvm_unreachable("<unknown operand type>");
  }

  if (closeP) O << ")";
}
const MCSection *TargetLoweringObjectFileELF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
                       Mangler *Mang, const TargetMachine &TM) const {
  // If we have -ffunction-section or -fdata-section then we should emit the
  // global value to a uniqued section specifically for it.
  bool EmitUniquedSection;
  if (Kind.isText())
    EmitUniquedSection = TM.getFunctionSections();
  else
    EmitUniquedSection = TM.getDataSections();

  // If this global is linkonce/weak and the target handles this by emitting it
  // into a 'uniqued' section name, create and return the section now.
  if ((GV->isWeakForLinker() || EmitUniquedSection) &&
      !Kind.isCommon()) {
    const char *Prefix;
    Prefix = getSectionPrefixForGlobal(Kind);

    SmallString<128> Name(Prefix, Prefix+strlen(Prefix));
    MCSymbol *Sym = Mang->getSymbol(GV);
    Name.append(Sym->getName().begin(), Sym->getName().end());
    StringRef Group = "";
    unsigned Flags = getELFSectionFlags(Kind);
    if (GV->isWeakForLinker()) {
      Group = Sym->getName();
      Flags |= ELF::SHF_GROUP;
    }

    return getContext().getELFSection(Name.str(),
                                      getELFSectionType(Name.str(), Kind),
                                      Flags, Kind, 0, Group);
  }

  if (Kind.isText()) return TextSection;

  if (Kind.isMergeable1ByteCString() ||
      Kind.isMergeable2ByteCString() ||
      Kind.isMergeable4ByteCString()) {

    // We also need alignment here.
    // FIXME: this is getting the alignment of the character, not the
    // alignment of the global!
    unsigned Align =
      TM.getDataLayout()->getPreferredAlignment(cast<GlobalVariable>(GV));

    const char *SizeSpec = ".rodata.str1.";
    if (Kind.isMergeable2ByteCString())
      SizeSpec = ".rodata.str2.";
    else if (Kind.isMergeable4ByteCString())
      SizeSpec = ".rodata.str4.";
    else
      assert(Kind.isMergeable1ByteCString() && "unknown string width");


    std::string Name = SizeSpec + utostr(Align);
    return getContext().getELFSection(Name, ELF::SHT_PROGBITS,
                                      ELF::SHF_ALLOC |
                                      ELF::SHF_MERGE |
                                      ELF::SHF_STRINGS,
                                      Kind);
  }

  if (Kind.isMergeableConst()) {
    if (Kind.isMergeableConst4() && MergeableConst4Section)
      return MergeableConst4Section;
    if (Kind.isMergeableConst8() && MergeableConst8Section)
      return MergeableConst8Section;
    if (Kind.isMergeableConst16() && MergeableConst16Section)
      return MergeableConst16Section;
    return ReadOnlySection;  // .const
  }

  if (Kind.isReadOnly())             return ReadOnlySection;

  if (Kind.isThreadData())           return TLSDataSection;
  if (Kind.isThreadBSS())            return TLSBSSSection;

  // Note: we claim that common symbols are put in BSSSection, but they are
  // really emitted with the magic .comm directive, which creates a symbol table
  // entry but not a section.
  if (Kind.isBSS() || Kind.isCommon()) return BSSSection;

  if (Kind.isDataNoRel())            return DataSection;
  if (Kind.isDataRelLocal())         return DataRelLocalSection;
  if (Kind.isDataRel())              return DataRelSection;
  if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection;

  assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
  return DataRelROSection;
}
/// printSymbolOperand - Print a raw symbol reference operand.  This handles
/// jump tables, constant pools, global address and external symbols, all of
/// which print to a label with various suffixes for relocation types etc.
static void printSymbolOperand(Cse523AsmPrinter &P, const MachineOperand &MO,
        raw_ostream &O) {
    switch (MO.getType()) {
        default: llvm_unreachable("unknown symbol type!");
        case MachineOperand::MO_ConstantPoolIndex:
                 O << *P.GetCPISymbol(MO.getIndex());
                 P.printOffset(MO.getOffset(), O);
                 break;
        case MachineOperand::MO_GlobalAddress: {
                                                   const GlobalValue *GV = MO.getGlobal();

                                                   MCSymbol *GVSym;
                                                   if (MO.getTargetFlags() == Cse523II::MO_DARWIN_STUB)
                                                       GVSym = P.getSymbolWithGlobalValueBase(GV, "$stub");
                                                   else if (MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY ||
                                                           MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY_PIC_BASE ||
                                                           MO.getTargetFlags() == Cse523II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
                                                       GVSym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
                                                   else
                                                       GVSym = P.getSymbol(GV);

                                                   // Handle dllimport linkage.
                                                   if (MO.getTargetFlags() == Cse523II::MO_DLLIMPORT)
                                                       GVSym =
                                                           P.OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName());

                                                   if (MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY ||
                                                           MO.getTargetFlags() == Cse523II::MO_DARWIN_NONLAZY_PIC_BASE) {
                                                       MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
                                                       MachineModuleInfoImpl::StubValueTy &StubSym =
                                                           P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym);
                                                       if (StubSym.getPointer() == 0)
                                                           StubSym = MachineModuleInfoImpl::
                                                               StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage());
                                                   } else if (MO.getTargetFlags() == Cse523II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){
                                                       MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
                                                       MachineModuleInfoImpl::StubValueTy &StubSym =
                                                           P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry(
                                                                   Sym);
                                                       if (StubSym.getPointer() == 0)
                                                           StubSym = MachineModuleInfoImpl::
                                                               StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage());
                                                   } else if (MO.getTargetFlags() == Cse523II::MO_DARWIN_STUB) {
                                                       MCSymbol *Sym = P.getSymbolWithGlobalValueBase(GV, "$stub");
                                                       MachineModuleInfoImpl::StubValueTy &StubSym =
                                                           P.MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym);
                                                       if (StubSym.getPointer() == 0)
                                                           StubSym = MachineModuleInfoImpl::
                                                               StubValueTy(P.getSymbol(GV), !GV->hasInternalLinkage());
                                                   }

                                                   // If the name begins with a dollar-sign, enclose it in parens.  We do this
                                                   // to avoid having it look like an integer immediate to the assembler.
                                                   if (GVSym->getName()[0] != '$')
                                                       O << *GVSym;
                                                   else
                                                       O << '(' << *GVSym << ')';
                                                   P.printOffset(MO.getOffset(), O);
                                                   break;
                                               }
    }

    switch (MO.getTargetFlags()) {
        default:
            llvm_unreachable("Unknown target flag on GV operand");
        case Cse523II::MO_NO_FLAG:    // No flag.
            break;
        case Cse523II::MO_DARWIN_NONLAZY:
        case Cse523II::MO_DLLIMPORT:
        case Cse523II::MO_DARWIN_STUB:
            // These affect the name of the symbol, not any suffix.
            break;
        case Cse523II::MO_GOT_ABSOLUTE_ADDRESS:
            O << " + [.-" << *P.MF->getPICBaseSymbol() << ']';
            break;
        case Cse523II::MO_PIC_BASE_OFFSET:
        case Cse523II::MO_DARWIN_NONLAZY_PIC_BASE:
        case Cse523II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
            O << '-' << *P.MF->getPICBaseSymbol();
            break;
        case Cse523II::MO_TLSGD:     O << "@TLSGD";     break;
        case Cse523II::MO_TLSLD:     O << "@TLSLD";     break;
        case Cse523II::MO_TLSLDM:    O << "@TLSLDM";    break;
        case Cse523II::MO_GOTTPOFF:  O << "@GOTTPOFF";  break;
        case Cse523II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
        case Cse523II::MO_TPOFF:     O << "@TPOFF";     break;
        case Cse523II::MO_DTPOFF:    O << "@DTPOFF";    break;
        case Cse523II::MO_NTPOFF:    O << "@NTPOFF";    break;
        case Cse523II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break;
        case Cse523II::MO_GOTPCREL:  O << "@GOTPCREL";  break;
        case Cse523II::MO_GOT:       O << "@GOT";       break;
        case Cse523II::MO_GOTOFF:    O << "@GOTOFF";    break;
        case Cse523II::MO_PLT:       O << "@PLT";       break;
        case Cse523II::MO_TLVP:      O << "@TLVP";      break;
        case Cse523II::MO_TLVP_PIC_BASE:
                                     O << "@TLVP" << '-' << *P.MF->getPICBaseSymbol();
                                     break;
        case Cse523II::MO_SECREL:    O << "@SECREL32";  break;
    }
}
Example #29
0
void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
  OS << "\t.ent\t" << Symbol.getName() << '\n';
}
Example #30
0
/// EmitExceptionTable - Emit landing pads and actions.
///
/// The general organization of the table is complex, but the basic concepts are
/// easy.  First there is a header which describes the location and organization
/// of the three components that follow.
///
///  1. The landing pad site information describes the range of code covered by
///     the try.  In our case it's an accumulation of the ranges covered by the
///     invokes in the try.  There is also a reference to the landing pad that
///     handles the exception once processed.  Finally an index into the actions
///     table.
///  2. The action table, in our case, is composed of pairs of type IDs and next
///     action offset.  Starting with the action index from the landing pad
///     site, each type ID is checked for a match to the current exception.  If
///     it matches then the exception and type id are passed on to the landing
///     pad.  Otherwise the next action is looked up.  This chain is terminated
///     with a next action of zero.  If no type id is found then the frame is
///     unwound and handling continues.
///  3. Type ID table contains references to all the C++ typeinfo for all
///     catches in the function.  This tables is reverse indexed base 1.
void DwarfException::EmitExceptionTable() {
  const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
  const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();

  // Sort the landing pads in order of their type ids.  This is used to fold
  // duplicate actions.
  SmallVector<const LandingPadInfo *, 64> LandingPads;
  LandingPads.reserve(PadInfos.size());

  for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
    LandingPads.push_back(&PadInfos[i]);

  std::sort(LandingPads.begin(), LandingPads.end(), PadLT);

  // Compute the actions table and gather the first action index for each
  // landing pad site.
  SmallVector<ActionEntry, 32> Actions;
  SmallVector<unsigned, 64> FirstActions;
  unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions);

  // Invokes and nounwind calls have entries in PadMap (due to being bracketed
  // by try-range labels when lowered).  Ordinary calls do not, so appropriate
  // try-ranges for them need be deduced when using DWARF exception handling.
  RangeMapType PadMap;
  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
    const LandingPadInfo *LandingPad = LandingPads[i];
    for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
      MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
      assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
      PadRange P = { i, j };
      PadMap[BeginLabel] = P;
    }
  }

  // Compute the call-site table.
  SmallVector<CallSiteEntry, 64> CallSites;
  ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions);

  // Final tallies.

  // Call sites.
  bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
  bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true;

  unsigned CallSiteTableLength;
  if (IsSJLJ)
    CallSiteTableLength = 0;
  else {
    unsigned SiteStartSize  = 4; // dwarf::DW_EH_PE_udata4
    unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
    unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
    CallSiteTableLength =
      CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
  }

  for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
    CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action);
    if (IsSJLJ)
      CallSiteTableLength += MCAsmInfo::getULEB128Size(i);
  }

  // Type infos.
  const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
  unsigned TTypeEncoding;
  unsigned TypeFormatSize;

  if (!HaveTTData) {
    // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say
    // that we're omitting that bit.
    TTypeEncoding = dwarf::DW_EH_PE_omit;
    // dwarf::DW_EH_PE_absptr
    TypeFormatSize = Asm->getDataLayout().getPointerSize();
  } else {
    // Okay, we have actual filters or typeinfos to emit.  As such, we need to
    // pick a type encoding for them.  We're about to emit a list of pointers to
    // typeinfo objects at the end of the LSDA.  However, unless we're in static
    // mode, this reference will require a relocation by the dynamic linker.
    //
    // Because of this, we have a couple of options:
    //
    //   1) If we are in -static mode, we can always use an absolute reference
    //      from the LSDA, because the static linker will resolve it.
    //
    //   2) Otherwise, if the LSDA section is writable, we can output the direct
    //      reference to the typeinfo and allow the dynamic linker to relocate
    //      it.  Since it is in a writable section, the dynamic linker won't
    //      have a problem.
    //
    //   3) Finally, if we're in PIC mode and the LDSA section isn't writable,
    //      we need to use some form of indirection.  For example, on Darwin,
    //      we can output a statically-relocatable reference to a dyld stub. The
    //      offset to the stub is constant, but the contents are in a section
    //      that is updated by the dynamic linker.  This is easy enough, but we
    //      need to tell the personality function of the unwinder to indirect
    //      through the dyld stub.
    //
    // FIXME: When (3) is actually implemented, we'll have to emit the stubs
    // somewhere.  This predicate should be moved to a shared location that is
    // in target-independent code.
    //
    TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding();
    TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
  }

  // Begin the exception table.
  // Sometimes we want not to emit the data into separate section (e.g. ARM
  // EHABI). In this case LSDASection will be NULL.
  if (LSDASection)
    Asm->OutStreamer.SwitchSection(LSDASection);
  Asm->EmitAlignment(2);

  // Emit the LSDA.
  MCSymbol *GCCETSym =
    Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+
                                      Twine(Asm->getFunctionNumber()));
  Asm->OutStreamer.EmitLabel(GCCETSym);
  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("exception",
                                                Asm->getFunctionNumber()));

  if (IsSJLJ)
    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("_LSDA_",
                                                  Asm->getFunctionNumber()));

  // Emit the LSDA header.
  Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
  Asm->EmitEncodingByte(TTypeEncoding, "@TType");

  // The type infos need to be aligned. GCC does this by inserting padding just
  // before the type infos. However, this changes the size of the exception
  // table, so you need to take this into account when you output the exception
  // table size. However, the size is output using a variable length encoding.
  // So by increasing the size by inserting padding, you may increase the number
  // of bytes used for writing the size. If it increases, say by one byte, then
  // you now need to output one less byte of padding to get the type infos
  // aligned. However this decreases the size of the exception table. This
  // changes the value you have to output for the exception table size. Due to
  // the variable length encoding, the number of bytes used for writing the
  // length may decrease. If so, you then have to increase the amount of
  // padding. And so on. If you look carefully at the GCC code you will see that
  // it indeed does this in a loop, going on and on until the values stabilize.
  // We chose another solution: don't output padding inside the table like GCC
  // does, instead output it before the table.
  unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
  unsigned CallSiteTableLengthSize =
    MCAsmInfo::getULEB128Size(CallSiteTableLength);
  unsigned TTypeBaseOffset =
    sizeof(int8_t) +                            // Call site format
    CallSiteTableLengthSize +                   // Call site table length size
    CallSiteTableLength +                       // Call site table length
    SizeActions +                               // Actions size
    SizeTypes;
  unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset);
  unsigned TotalSize =
    sizeof(int8_t) +                            // LPStart format
    sizeof(int8_t) +                            // TType format
    (HaveTTData ? TTypeBaseOffsetSize : 0) +    // TType base offset size
    TTypeBaseOffset;                            // TType base offset
  unsigned SizeAlign = (4 - TotalSize) & 3;

  if (HaveTTData) {
    // Account for any extra padding that will be added to the call site table
    // length.
    Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign);
    SizeAlign = 0;
  }

  bool VerboseAsm = Asm->OutStreamer.isVerboseAsm();

  // SjLj Exception handling
  if (IsSJLJ) {
    Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");

    // Add extra padding if it wasn't added to the TType base offset.
    Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);

    // Emit the landing pad site information.
    unsigned idx = 0;
    for (SmallVectorImpl<CallSiteEntry>::const_iterator
         I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
      const CallSiteEntry &S = *I;

      // Offset of the landing pad, counted in 16-byte bundles relative to the
      // @LPStart address.
      if (VerboseAsm) {
        Asm->OutStreamer.AddComment(">> Call Site " + Twine(idx) + " <<");
        Asm->OutStreamer.AddComment("  On exception at call site "+Twine(idx));
      }
      Asm->EmitULEB128(idx);

      // Offset of the first associated action record, relative to the start of
      // the action table. This value is biased by 1 (1 indicates the start of
      // the action table), and 0 indicates that there are no actions.
      if (VerboseAsm) {
        if (S.Action == 0)
          Asm->OutStreamer.AddComment("  Action: cleanup");
        else
          Asm->OutStreamer.AddComment("  Action: " +
                                      Twine((S.Action - 1) / 2 + 1));
      }
      Asm->EmitULEB128(S.Action);
    }
  } else {
    // DWARF Exception handling
    assert(Asm->MAI->isExceptionHandlingDwarf());

    // The call-site table is a list of all call sites that may throw an
    // exception (including C++ 'throw' statements) in the procedure
    // fragment. It immediately follows the LSDA header. Each entry indicates,
    // for a given call, the first corresponding action record and corresponding
    // landing pad.
    //
    // The table begins with the number of bytes, stored as an LEB128
    // compressed, unsigned integer. The records immediately follow the record
    // count. They are sorted in increasing call-site address. Each record
    // indicates:
    //
    //   * The position of the call-site.
    //   * The position of the landing pad.
    //   * The first action record for that call site.
    //
    // A missing entry in the call-site table indicates that a call is not
    // supposed to throw.

    // Emit the landing pad call site table.
    Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");

    // Add extra padding if it wasn't added to the TType base offset.
    Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);

    unsigned Entry = 0;
    for (SmallVectorImpl<CallSiteEntry>::const_iterator
         I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
      const CallSiteEntry &S = *I;

      MCSymbol *EHFuncBeginSym =
        Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber());

      MCSymbol *BeginLabel = S.BeginLabel;
      if (BeginLabel == 0)
        BeginLabel = EHFuncBeginSym;
      MCSymbol *EndLabel = S.EndLabel;
      if (EndLabel == 0)
        EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber());


      // Offset of the call site relative to the previous call site, counted in
      // number of 16-byte bundles. The first call site is counted relative to
      // the start of the procedure fragment.
      if (VerboseAsm)
        Asm->OutStreamer.AddComment(">> Call Site " + Twine(++Entry) + " <<");
      Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
      if (VerboseAsm)
        Asm->OutStreamer.AddComment(Twine("  Call between ") +
                                    BeginLabel->getName() + " and " +
                                    EndLabel->getName());
      Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);

      // Offset of the landing pad, counted in 16-byte bundles relative to the
      // @LPStart address.
      if (!S.PadLabel) {
        if (VerboseAsm)
          Asm->OutStreamer.AddComment("    has no landing pad");
        Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
      } else {
        if (VerboseAsm)
          Asm->OutStreamer.AddComment(Twine("    jumps to ") +
                                      S.PadLabel->getName());
        Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4);
      }

      // Offset of the first associated action record, relative to the start of
      // the action table. This value is biased by 1 (1 indicates the start of
      // the action table), and 0 indicates that there are no actions.
      if (VerboseAsm) {
        if (S.Action == 0)
          Asm->OutStreamer.AddComment("  On action: cleanup");
        else
          Asm->OutStreamer.AddComment("  On action: " +
                                      Twine((S.Action - 1) / 2 + 1));
      }
      Asm->EmitULEB128(S.Action);
    }
  }

  // Emit the Action Table.
  int Entry = 0;
  for (SmallVectorImpl<ActionEntry>::const_iterator
         I = Actions.begin(), E = Actions.end(); I != E; ++I) {
    const ActionEntry &Action = *I;

    if (VerboseAsm) {
      // Emit comments that decode the action table.
      Asm->OutStreamer.AddComment(">> Action Record " + Twine(++Entry) + " <<");
    }

    // Type Filter
    //
    //   Used by the runtime to match the type of the thrown exception to the
    //   type of the catch clauses or the types in the exception specification.
    if (VerboseAsm) {
      if (Action.ValueForTypeID > 0)
        Asm->OutStreamer.AddComment("  Catch TypeInfo " +
                                    Twine(Action.ValueForTypeID));
      else if (Action.ValueForTypeID < 0)
        Asm->OutStreamer.AddComment("  Filter TypeInfo " +
                                    Twine(Action.ValueForTypeID));
      else
        Asm->OutStreamer.AddComment("  Cleanup");
    }
    Asm->EmitSLEB128(Action.ValueForTypeID);

    // Action Record
    //
    //   Self-relative signed displacement in bytes of the next action record,
    //   or 0 if there is no next action record.
    if (VerboseAsm) {
      if (Action.NextAction == 0) {
        Asm->OutStreamer.AddComment("  No further actions");
      } else {
        unsigned NextAction = Entry + (Action.NextAction + 1) / 2;
        Asm->OutStreamer.AddComment("  Continue to action "+Twine(NextAction));
      }
    }
    Asm->EmitSLEB128(Action.NextAction);
  }

  // Emit the Catch TypeInfos.
  if (VerboseAsm && !TypeInfos.empty()) {
    Asm->OutStreamer.AddComment(">> Catch TypeInfos <<");
    Asm->OutStreamer.AddBlankLine();
    Entry = TypeInfos.size();
  }

  for (std::vector<const GlobalVariable *>::const_reverse_iterator
         I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) {
    const GlobalVariable *GV = *I;
    if (VerboseAsm)
      Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--));
    if (GV)
      Asm->EmitReference(GV, TTypeEncoding);
    else
      Asm->OutStreamer.EmitIntValue(0,Asm->GetSizeOfEncodedValue(TTypeEncoding),
                                    0);
  }

  // Emit the Exception Specifications.
  if (VerboseAsm && !FilterIds.empty()) {
    Asm->OutStreamer.AddComment(">> Filter TypeInfos <<");
    Asm->OutStreamer.AddBlankLine();
    Entry = 0;
  }
  for (std::vector<unsigned>::const_iterator
         I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
    unsigned TypeID = *I;
    if (VerboseAsm) {
      --Entry;
      if (TypeID != 0)
        Asm->OutStreamer.AddComment("FilterInfo " + Twine(Entry));
    }

    Asm->EmitULEB128(TypeID);
  }

  Asm->EmitAlignment(2);
}