/// Find the target operand flags that describe how a global value should be /// referenced for the current subtarget. unsigned char AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // MachO large model always goes via a GOT, simply to get a single 8-byte // absolute relocation on all global addresses. if (TM.getCodeModel() == CodeModel::Large && isTargetMachO()) return AArch64II::MO_GOT; if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) { if (GV->hasDLLImportStorageClass()) return AArch64II::MO_GOT | AArch64II::MO_DLLIMPORT; if (getTargetTriple().isOSWindows()) return AArch64II::MO_GOT | AArch64II::MO_COFFSTUB; return AArch64II::MO_GOT; } // The small code model's direct accesses use ADRP, which cannot // necessarily produce the value 0 (if the code is above 4GB). // Same for the tiny code model, where we have a pc relative LDR. if ((useSmallAddressing() || TM.getCodeModel() == CodeModel::Tiny) && GV->hasExternalWeakLinkage()) return AArch64II::MO_GOT; return AArch64II::MO_NO_FLAG; }
/// Initialize - this method must be called before any actual lowering is /// done. This specifies the current context for codegen, and gives the /// lowering implementations a chance to set up their default sections. void TargetLoweringObjectFile::Initialize(MCContext &ctx, const TargetMachine &TM) { Ctx = &ctx; DL = TM.getDataLayout(); InitMCObjectFileInfo(TM.getTargetTriple(), TM.getRelocationModel(), TM.getCodeModel(), *Ctx); }
/// Initialize - this method must be called before any actual lowering is /// done. This specifies the current context for codegen, and gives the /// lowering implementations a chance to set up their default sections. void TargetLoweringObjectFile::Initialize(MCContext &ctx, const TargetMachine &TM) { Ctx = &ctx; // `Initialize` can be called more than once. if (Mang != nullptr) delete Mang; Mang = new Mangler(); InitMCObjectFileInfo(TM.getTargetTriple(), TM.isPositionIndependent(), TM.getCodeModel(), *Ctx); }
/// Find the target operand flags that describe how a global value should be /// referenced for the current subtarget. unsigned char AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // MachO large model always goes via a GOT, simply to get a single 8-byte // absolute relocation on all global addresses. if (TM.getCodeModel() == CodeModel::Large && isTargetMachO()) return AArch64II::MO_GOT; if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) return AArch64II::MO_GOT; // The small code mode's direct accesses use ADRP, which cannot necessarily // produce the value 0 (if the code is above 4GB). if (TM.getCodeModel() == CodeModel::Small && GV->hasExternalWeakLinkage()) return AArch64II::MO_GOT; return AArch64II::MO_NO_FLAG; }
/// ClassifyGlobalReference - Find the target operand flags that describe /// how a global value should be referenced for the current subtarget. unsigned char ARM64Subtarget::ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // Determine whether this is a reference to a definition or a declaration. // Materializable GVs (in JIT lazy compilation mode) do not require an extra // load from stub. bool isDecl = GV->hasAvailableExternallyLinkage(); if (GV->isDeclaration() && !GV->isMaterializable()) isDecl = true; // MachO large model always goes via a GOT, simply to get a single 8-byte // absolute relocation on all global addresses. if (TM.getCodeModel() == CodeModel::Large && isTargetMachO()) return ARM64II::MO_GOT; // The small code mode's direct accesses use ADRP, which cannot necessarily // produce the value 0 (if the code is above 4GB). Therefore they must use the // GOT. if (TM.getCodeModel() == CodeModel::Small && GV->isWeakForLinker() && isDecl) return ARM64II::MO_GOT; // If symbol visibility is hidden, the extra load is not needed if // the symbol is definitely defined in the current translation unit. // The handling of non-hidden symbols in PIC mode is rather target-dependent: // + On MachO, if the symbol is defined in this module the GOT can be // skipped. // + On ELF, the R_AARCH64_COPY relocation means that even symbols actually // defined could end up in unexpected places. Use a GOT. if (TM.getRelocationModel() != Reloc::Static && GV->hasDefaultVisibility()) { if (isTargetMachO()) return (isDecl || GV->isWeakForLinker()) ? ARM64II::MO_GOT : ARM64II::MO_NO_FLAG; else // No need to go through the GOT for local symbols on ELF. return GV->hasLocalLinkage() ? ARM64II::MO_NO_FLAG : ARM64II::MO_GOT; } return ARM64II::MO_NO_FLAG; }
/// ClassifyGlobalReference - Find the target operand flags that describe /// how a global value should be referenced for the current subtarget. unsigned char AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { bool isDecl = GV->isDeclarationForLinker(); // MachO large model always goes via a GOT, simply to get a single 8-byte // absolute relocation on all global addresses. if (TM.getCodeModel() == CodeModel::Large && isTargetMachO()) return AArch64II::MO_GOT; // The small code mode's direct accesses use ADRP, which cannot necessarily // produce the value 0 (if the code is above 4GB). if (TM.getCodeModel() == CodeModel::Small && GV->isWeakForLinker() && isDecl) { // In PIC mode use the GOT, but in absolute mode use a constant pool load. if (TM.getRelocationModel() == Reloc::Static) return AArch64II::MO_CONSTPOOL; else return AArch64II::MO_GOT; } // If symbol visibility is hidden, the extra load is not needed if // the symbol is definitely defined in the current translation unit. // The handling of non-hidden symbols in PIC mode is rather target-dependent: // + On MachO, if the symbol is defined in this module the GOT can be // skipped. // + On ELF, the R_AARCH64_COPY relocation means that even symbols actually // defined could end up in unexpected places. Use a GOT. if (TM.getRelocationModel() != Reloc::Static && GV->hasDefaultVisibility()) { if (isTargetMachO()) return (isDecl || GV->isWeakForLinker()) ? AArch64II::MO_GOT : AArch64II::MO_NO_FLAG; else // No need to go through the GOT for local symbols on ELF. return GV->hasLocalLinkage() ? AArch64II::MO_NO_FLAG : AArch64II::MO_GOT; } return AArch64II::MO_NO_FLAG; }
/// Find the target operand flags that describe how a global value should be /// referenced for the current subtarget. unsigned char AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // MachO large model always goes via a GOT, simply to get a single 8-byte // absolute relocation on all global addresses. if (TM.getCodeModel() == CodeModel::Large && isTargetMachO()) return AArch64II::MO_GOT; Reloc::Model RM = TM.getRelocationModel(); if (!shouldAssumeDSOLocal(RM, TargetTriple, *GV->getParent(), GV)) return AArch64II::MO_GOT; // The small code mode's direct accesses use ADRP, which cannot necessarily // produce the value 0 (if the code is above 4GB). if (TM.getCodeModel() == CodeModel::Small && GV->hasExternalWeakLinkage()) { // In PIC mode use the GOT, but in absolute mode use a constant pool load. if (RM == Reloc::Static) return AArch64II::MO_CONSTPOOL; else return AArch64II::MO_GOT; } return AArch64II::MO_NO_FLAG; }
unsigned char AArch64Subtarget::classifyGlobalFunctionReference( const GlobalValue *GV, const TargetMachine &TM) const { // MachO large model always goes via a GOT, because we don't have the // relocations available to do anything else.. if (TM.getCodeModel() == CodeModel::Large && isTargetMachO() && !GV->hasInternalLinkage()) return AArch64II::MO_GOT; // NonLazyBind goes via GOT unless we know it's available locally. auto *F = dyn_cast<Function>(GV); if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) && !TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) return AArch64II::MO_GOT; return AArch64II::MO_NO_FLAG; }
/// Classify a global variable reference for the current subtarget according to /// how we should reference it in a non-pcrel context. unsigned char X86Subtarget:: ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // DLLImport only exists on windows, it is implemented as a load from a // DLLIMPORT stub. if (GV->hasDLLImportStorageClass()) return X86II::MO_DLLIMPORT; bool isDef = GV->isStrongDefinitionForLinker(); // X86-64 in PIC mode. if (isPICStyleRIPRel()) { // Large model never uses stubs. if (TM.getCodeModel() == CodeModel::Large) return X86II::MO_NO_FLAG; if (isTargetDarwin()) { // If symbol visibility is hidden, the extra load is not needed if // target is x86-64 or the symbol is definitely defined in the current // translation unit. if (GV->hasDefaultVisibility() && !isDef) return X86II::MO_GOTPCREL; } else if (!isTargetWin64()) { assert(isTargetELF() && "Unknown rip-relative target"); // Extra load is needed for all externally visible. if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility()) return X86II::MO_GOTPCREL; } return X86II::MO_NO_FLAG; } if (isPICStyleGOT()) { // 32-bit ELF targets. // Extra load is needed for all externally visible. if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) return X86II::MO_GOTOFF; return X86II::MO_GOT; } if (isPICStyleStubPIC()) { // Darwin/32 in PIC mode. // Determine whether we have a stub reference and/or whether the reference // is relative to the PIC base or not. // If this is a strong reference to a definition, it is definitely not // through a stub. if (isDef) return X86II::MO_PIC_BASE_OFFSET; // Unless we have a symbol with hidden visibility, we have to go through a // normal $non_lazy_ptr stub because this symbol might be resolved late. if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. return X86II::MO_DARWIN_NONLAZY_PIC_BASE; // If symbol visibility is hidden, we have a stub for common symbol // references and external declarations. if (GV->isDeclarationForLinker() || GV->hasCommonLinkage()) { // Hidden $non_lazy_ptr reference. return X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE; } // Otherwise, no stub. return X86II::MO_PIC_BASE_OFFSET; } if (isPICStyleStubNoDynamic()) { // Darwin/32 in -mdynamic-no-pic mode. // Determine whether we have a stub reference. // If this is a strong reference to a definition, it is definitely not // through a stub. if (isDef) return X86II::MO_NO_FLAG; // Unless we have a symbol with hidden visibility, we have to go through a // normal $non_lazy_ptr stub because this symbol might be resolved late. if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. return X86II::MO_DARWIN_NONLAZY; // Otherwise, no stub. return X86II::MO_NO_FLAG; } // Direct static reference to global. return X86II::MO_NO_FLAG; }
int LLVMTargetMachineAssembleToOutputStream(LLVMTargetMachineRef TM, LLVMMemoryBufferRef Mem, void *JOStream, LLVMBool RelaxAll, LLVMBool NoExecStack, char **ErrorMessage) { *ErrorMessage = NULL; #if !defined(WIN32) locale_t loc = newlocale(LC_ALL_MASK, "C", 0); locale_t oldLoc = uselocale(loc); #endif TargetMachine *TheTargetMachine = unwrap(TM); const Target *TheTarget = &(TheTargetMachine->getTarget()); std::string TripleName = TheTargetMachine->getTargetTriple().str(); std::string MCPU = TheTargetMachine->getTargetCPU().str(); std::string FeaturesStr = TheTargetMachine->getTargetFeatureString().str(); Reloc::Model RelocModel = TheTargetMachine->getRelocationModel(); CodeModel::Model CMModel = TheTargetMachine->getCodeModel(); std::unique_ptr<MemoryBuffer> Buffer(unwrap(Mem)); std::string DiagStr; raw_string_ostream DiagStream(DiagStr); SourceMgr SrcMgr; SrcMgr.setDiagHandler(assembleDiagHandler, &DiagStream); // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); // Record the location of the include directories so that the lexer can find // it later. // SrcMgr.setIncludeDirs(IncludeDirs); std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); raw_java_ostream& Out = *((raw_java_ostream*) JOStream); std::unique_ptr<MCStreamer> Str; MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, Out, CE, *STI, RelaxAll != 0)); if (NoExecStack != 0) Str->InitSections(true); MCTargetOptions MCOptions; std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, *Str, *MAI)); std::unique_ptr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); if (!TAP) { *ErrorMessage = strdup("this target does not support assembly parsing"); goto done; } Parser->setTargetParser(*TAP.get()); if (Parser->Run(false)) { *ErrorMessage = strdup(DiagStream.str().c_str()); goto done; } Out.flush(); done: #if !defined(WIN32) uselocale(oldLoc); freelocale(loc); #endif return *ErrorMessage ? 1 : 0; }