/// ParseDirectiveTBSS /// ::= .tbss identifier, size, align bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { SMLoc IDLoc = getLexer().getLoc(); StringRef Name; if (getParser().ParseIdentifier(Name)) return TokError("expected identifier in directive"); // Handle the identifier as the key symbol. MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); int64_t Size; SMLoc SizeLoc = getLexer().getLoc(); if (getParser().ParseAbsoluteExpression(Size)) return true; int64_t Pow2Alignment = 0; SMLoc Pow2AlignmentLoc; if (getLexer().is(AsmToken::Comma)) { Lex(); Pow2AlignmentLoc = getLexer().getLoc(); if (getParser().ParseAbsoluteExpression(Pow2Alignment)) return true; } if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.tbss' directive"); Lex(); if (Size < 0) return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than" "zero"); // FIXME: Diagnose overflow. if (Pow2Alignment < 0) return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less" "than zero"); if (!Sym->isUndefined()) return Error(IDLoc, "invalid symbol redefinition"); getStreamer().EmitTBSSSymbol(getContext().getMachOSection( "__DATA", "__thread_bss", MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, 0, SectionKind::getThreadBSS()), Sym, Size, 1 << Pow2Alignment); return false; }
bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) { // Undefined symbols are always extern. if (S.isUndefined()) return true; // References to weak definitions require external relocation entries; the // definition may not always be the one in the same object file. if (cast<MCSymbolMachO>(S).isWeakDefinition()) return true; // Otherwise, we can use an internal relocation. return false; }
void MCELFStreamer::ChangeSection(const MCSection *Section, const MCExpr *Subsection) { MCSectionData *CurSection = getCurrentSectionData(); if (CurSection && CurSection->isBundleLocked()) report_fatal_error("Unterminated .bundle_lock when changing a section"); MCAssembler &Asm = getAssembler(); auto *SectionELF = static_cast<const MCSectionELF *>(Section); const MCSymbol *Grp = SectionELF->getGroup(); if (Grp) Asm.getOrCreateSymbolData(*Grp); this->MCObjectStreamer::ChangeSection(Section, Subsection); MCSymbol *SectionSymbol = getContext().getOrCreateSectionSymbol(*SectionELF); if (SectionSymbol->isUndefined()) { EmitLabel(SectionSymbol); MCELF::SetType(Asm.getSymbolData(*SectionSymbol), ELF::STT_SECTION); } }
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(); }
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; }
/// ParseDirectiveZerofill /// ::= .zerofill segname , sectname [, identifier , size_expression [ /// , align_expression ]] bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { StringRef Segment; if (getParser().ParseIdentifier(Segment)) return TokError("expected segment name after '.zerofill' directive"); if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); StringRef Section; if (getParser().ParseIdentifier(Section)) return TokError("expected section name after comma in '.zerofill' " "directive"); // If this is the end of the line all that was wanted was to create the // the section but with no symbol. if (getLexer().is(AsmToken::EndOfStatement)) { // Create the zerofill section but no symbol getStreamer().EmitZerofill(getContext().getMachOSection( Segment, Section, MCSectionMachO::S_ZEROFILL, 0, SectionKind::getBSS())); return false; } if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); SMLoc IDLoc = getLexer().getLoc(); StringRef IDStr; if (getParser().ParseIdentifier(IDStr)) return TokError("expected identifier in directive"); // handle the identifier as the key symbol. MCSymbol *Sym = getContext().GetOrCreateSymbol(IDStr); if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); int64_t Size; SMLoc SizeLoc = getLexer().getLoc(); if (getParser().ParseAbsoluteExpression(Size)) return true; int64_t Pow2Alignment = 0; SMLoc Pow2AlignmentLoc; if (getLexer().is(AsmToken::Comma)) { Lex(); Pow2AlignmentLoc = getLexer().getLoc(); if (getParser().ParseAbsoluteExpression(Pow2Alignment)) return true; } if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.zerofill' directive"); Lex(); if (Size < 0) return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " "than zero"); // NOTE: The alignment in the directive is a power of 2 value, the assembler // may internally end up wanting an alignment in bytes. // FIXME: Diagnose overflow. if (Pow2Alignment < 0) return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " "can't be less than zero"); if (!Sym->isUndefined()) return Error(IDLoc, "invalid symbol redefinition"); // Create the zerofill Symbol with Size and Pow2Alignment // // FIXME: Arch specific. getStreamer().EmitZerofill(getContext().getMachOSection( Segment, Section, MCSectionMachO::S_ZEROFILL, 0, SectionKind::getBSS()), Sym, Size, 1 << Pow2Alignment); return false; }
/// ParseDirectiveComm /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] bool MachOAsmParser::ParseDirectiveComm(bool IsLocal) { SMLoc IDLoc = Lexer.getLoc(); StringRef Name; if (ParseIdentifier(Name)) return TokError("expected identifier in directive"); // Handle the identifier as the key symbol. MCSymbol *Sym = CreateSymbol(Name); if (Lexer.isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); int64_t Size; SMLoc SizeLoc = Lexer.getLoc(); if (ParseAbsoluteExpression(Size)) return true; int64_t Pow2Alignment = 0; SMLoc Pow2AlignmentLoc; if (Lexer.is(AsmToken::Comma)) { Lex(); Pow2AlignmentLoc = Lexer.getLoc(); if (ParseAbsoluteExpression(Pow2Alignment)) return true; // If this target takes alignments in bytes (not log) validate and convert. if (Lexer.getMAI().getAlignmentIsInBytes()) { if (!isPowerOf2_64(Pow2Alignment)) return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); Pow2Alignment = Log2_64(Pow2Alignment); } } if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.comm' or '.lcomm' directive"); Lex(); // NOTE: a size of zero for a .comm should create a undefined symbol // but a size of .lcomm creates a bss symbol of size zero. if (Size < 0) return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " "be less than zero"); // NOTE: The alignment in the directive is a power of 2 value, the assembler // may internally end up wanting an alignment in bytes. // FIXME: Diagnose overflow. if (Pow2Alignment < 0) return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " "alignment, can't be less than zero"); if (!Sym->isUndefined()) return Error(IDLoc, "invalid symbol redefinition"); // '.lcomm' is equivalent to '.zerofill'. // Create the Symbol as a common or local common with Size and Pow2Alignment if (IsLocal) { Out.EmitZerofill(Ctx.getMachOSection("__DATA", "__bss", MCSectionMachO::S_ZEROFILL, 0, SectionKind::getBSS()), Sym, Size, 1 << Pow2Alignment); return false; } Out.EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); return false; }
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!"); SmallString<128> decl; raw_svector_ostream os(decl); // check if it is defined in some other translation unit if (gv->isDeclaration()) os << ".extern "; // state space: e.g., .global os << '.' << getStateSpaceName(gv->getType()->getAddressSpace()) << ' '; // alignment (optional) unsigned alignment = gv->getAlignment(); if (alignment != 0) os << ".align " << gv->getAlignment() << ' '; if (PointerType::classof(gv->getType())) { PointerType* pointerTy = dyn_cast<PointerType>(gv->getType()); Type* elementTy = pointerTy->getElementType(); if (elementTy->isArrayTy()) { assert(elementTy->isArrayTy() && "Only pointers to arrays are supported"); ArrayType* arrayTy = dyn_cast<ArrayType>(elementTy); elementTy = arrayTy->getElementType(); unsigned numElements = arrayTy->getNumElements(); while (elementTy->isArrayTy()) { arrayTy = dyn_cast<ArrayType>(elementTy); elementTy = arrayTy->getElementType(); numElements *= arrayTy->getNumElements(); } // FIXME: isPrimitiveType() == false for i16? assert(elementTy->isSingleValueType() && "Non-primitive types are not handled"); // Find the size of the element in bits unsigned elementSize = elementTy->getPrimitiveSizeInBits(); os << ".b" << elementSize << ' ' << gvsym->getName() << '[' << numElements << ']'; } else { os << ".b8" << gvsym->getName() << "[]"; } // handle string constants (assume ConstantArray means string) if (gv->hasInitializer()) { const Constant *C = gv->getInitializer(); if (const ConstantArray *CA = dyn_cast<ConstantArray>(C)) { os << " = {"; for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { if (i > 0) os << ','; os << "0x"; os.write_hex(cast<ConstantInt>(CA->getOperand(i))->getZExtValue()); } os << '}'; } } } else { // Note: this is currently the fall-through case and most likely generates // incorrect code. os << getTypeName(gv->getType()) << ' ' << gvsym->getName(); if (isa<ArrayType>(gv->getType()) || isa<PointerType>(gv->getType())) os << "[]"; } os << ';'; OutStreamer.EmitRawText(os.str()); OutStreamer.AddBlankLine(); }