Emit ARM build-attributes in the file scope (as header). The ARM linker will check that .o files declare compatible build attributes (e.g., all claim hard-float calling convention, all claim VFP-vX ,etc.). Thus, in order to set up cross tests that link LLC generated code against and Subzero generated code, we need the build attributes to be compatible. Pick ARMv7, hard-float calling convention, and neon, etc. which we use for PNaCl LLVM. Will probably have to reorganize to keep in sync once the ELF writer also emits this. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076 R=kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/1171563002.
diff --git a/src/IceCompiler.cpp b/src/IceCompiler.cpp index da9172c..2db7abc 100644 --- a/src/IceCompiler.cpp +++ b/src/IceCompiler.cpp
@@ -102,11 +102,7 @@ TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx); - if (Ctx.getFlags().getOutFileType() == FT_Elf) { - TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); - Ctx.getObjectWriter()->writeInitialELFHeader(); - } - + Ctx.emitFileHeader(); Ctx.startWorkerThreads(); std::unique_ptr<Translator> Translator;
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp index 87421bc..8ed4d76 100644 --- a/src/IceGlobalContext.cpp +++ b/src/IceGlobalContext.cpp
@@ -400,6 +400,17 @@ } // end of anonymous namespace +void GlobalContext::emitFileHeader() { + TimerMarker T1(Ice::TimerStack::TT_emit, this); + if (getFlags().getOutFileType() == FT_Elf) { + getObjectWriter()->writeInitialELFHeader(); + } else { + if (!ALLOW_DUMP) + llvm::report_fatal_error("emitFileHeader for non-ELF"); + TargetHeaderLowering::createLowering(this)->lower(); + } +} + void GlobalContext::emitItems() { const bool Threaded = !getFlags().isSequential(); // Pending is a vector containing the reassembled, ordered list of
diff --git a/src/IceGlobalContext.h b/src/IceGlobalContext.h index 9fb997c..763a75b 100644 --- a/src/IceGlobalContext.h +++ b/src/IceGlobalContext.h
@@ -300,6 +300,9 @@ // Notifies that no more work will be added to the work queue. void optQueueNotifyEnd() { OptQ.notifyEnd(); } + // Emit file header for output file. + void emitFileHeader(); + void emitQueueBlockingPush(EmitterWorkItem *Item); EmitterWorkItem *emitQueueBlockingPop(); void emitQueueNotifyEnd() { EmitQ.notifyEnd(); }
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp index b8f11bb..aefad00 100644 --- a/src/IceTargetLowering.cpp +++ b/src/IceTargetLowering.cpp
@@ -437,13 +437,25 @@ TargetArch Target = Ctx->getFlags().getTargetArch(); #define SUBZERO_TARGET(X) \ if (Target == Target_##X) \ - return std::unique_ptr<TargetDataLowering>(TargetData##X::create(Ctx)); + return TargetData##X::create(Ctx); #include "llvm/Config/SZTargets.def" - llvm_unreachable("Unsupported target data lowering"); - return nullptr; + llvm::report_fatal_error("Unsupported target data lowering"); } TargetDataLowering::~TargetDataLowering() {} +std::unique_ptr<TargetHeaderLowering> +TargetHeaderLowering::createLowering(GlobalContext *Ctx) { + TargetArch Target = Ctx->getFlags().getTargetArch(); +#define SUBZERO_TARGET(X) \ + if (Target == Target_##X) \ + return TargetHeader##X::create(Ctx); +#include "llvm/Config/SZTargets.def" + + llvm::report_fatal_error("Unsupported target header lowering"); +} + +TargetHeaderLowering::~TargetHeaderLowering() {} + } // end of namespace Ice
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h index a2eac4b..069b49e 100644 --- a/src/IceTargetLowering.h +++ b/src/IceTargetLowering.h
@@ -389,6 +389,26 @@ GlobalContext *Ctx; }; +// TargetHeaderLowering is used to "lower" the header of an output file. +// It writes out the target-specific header attributes. E.g., for ARM +// this writes out the build attributes (float ABI, etc.). +class TargetHeaderLowering { + TargetHeaderLowering() = delete; + TargetHeaderLowering(const TargetHeaderLowering &) = delete; + TargetHeaderLowering &operator=(const TargetHeaderLowering &) = delete; + +public: + static std::unique_ptr<TargetHeaderLowering> + createLowering(GlobalContext *Ctx); + virtual ~TargetHeaderLowering(); + + virtual void lower() {} + +protected: + explicit TargetHeaderLowering(GlobalContext *Ctx) : Ctx(Ctx) {} + GlobalContext *Ctx; +}; + } // end of namespace Ice #endif // SUBZERO_SRC_ICETARGETLOWERING_H
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp index 8f7c331..5b7bccc 100644 --- a/src/IceTargetLoweringARM32.cpp +++ b/src/IceTargetLoweringARM32.cpp
@@ -2225,4 +2225,43 @@ UnimplementedError(Ctx->getFlags()); } +TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx) + : TargetHeaderLowering(Ctx) {} + +void TargetHeaderARM32::lower() { + OstreamLocker L(Ctx); + Ostream &Str = Ctx->getStrEmit(); + Str << ".syntax unified\n"; + // Emit build attributes in format: .eabi_attribute TAG, VALUE. + // See Sec. 2 of "Addenda to, and Errata in the ABI for the ARM architecture" + // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf + // + // Tag_conformance should be be emitted first in a file-scope + // sub-subsection of the first public subsection of the attributes. + Str << ".eabi_attribute 67, \"2.09\" @ Tag_conformance\n"; + // Chromebooks are at least A15, but do A9 for higher compat. + Str << ".cpu cortex-a9\n" + << ".eabi_attribute 6, 10 @ Tag_CPU_arch: ARMv7\n" + << ".eabi_attribute 7, 65 @ Tag_CPU_arch_profile: App profile\n"; + Str << ".eabi_attribute 8, 1 @ Tag_ARM_ISA_use: Yes\n" + << ".eabi_attribute 9, 2 @ Tag_THUMB_ISA_use: Thumb-2\n"; + // TODO(jvoung): check other CPU features like HW div. + Str << ".fpu neon\n" + << ".eabi_attribute 17, 1 @ Tag_ABI_PCS_GOT_use: permit directly\n" + << ".eabi_attribute 20, 1 @ Tag_ABI_FP_denormal\n" + << ".eabi_attribute 21, 1 @ Tag_ABI_FP_exceptions\n" + << ".eabi_attribute 23, 3 @ Tag_ABI_FP_number_model: IEEE 754\n" + << ".eabi_attribute 34, 1 @ Tag_CPU_unaligned_access\n" + << ".eabi_attribute 24, 1 @ Tag_ABI_align_needed: 8-byte\n" + << ".eabi_attribute 25, 1 @ Tag_ABI_align_preserved: 8-byte\n" + << ".eabi_attribute 28, 1 @ Tag_ABI_VFP_args\n" + << ".eabi_attribute 36, 1 @ Tag_FP_HP_extension\n" + << ".eabi_attribute 38, 1 @ Tag_ABI_FP_16bit_format\n" + << ".eabi_attribute 42, 1 @ Tag_MPextension_use\n" + << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; + // Technically R9 is used for TLS with Sandboxing, and we reserve it. + // However, for compatibility with current NaCl LLVM, don't claim that. + Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; +} + } // end of namespace Ice
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h index 53c9895..bd7d528 100644 --- a/src/IceTargetLoweringARM32.h +++ b/src/IceTargetLoweringARM32.h
@@ -308,8 +308,8 @@ TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; public: - static TargetDataLowering *create(GlobalContext *Ctx) { - return new TargetDataARM32(Ctx); + static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { + return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx)); } void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) const final; @@ -324,6 +324,25 @@ template <typename T> static void emitConstantPool(GlobalContext *Ctx); }; +class TargetHeaderARM32 final : public TargetHeaderLowering { + TargetHeaderARM32() = delete; + TargetHeaderARM32(const TargetHeaderARM32 &) = delete; + TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete; + +public: + static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) { + return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx)); + } + + void lower(); + +protected: + explicit TargetHeaderARM32(GlobalContext *Ctx); + +private: + ~TargetHeaderARM32() = default; +}; + } // end of namespace Ice #endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp index 9ca10b7..494f233 100644 --- a/src/IceTargetLoweringMIPS32.cpp +++ b/src/IceTargetLoweringMIPS32.cpp
@@ -702,4 +702,7 @@ llvm::report_fatal_error("Not yet implemented"); } +TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) + : TargetHeaderLowering(Ctx) {} + } // end of namespace Ice
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h index cb583b5..b6c325a 100644 --- a/src/IceTargetLoweringMIPS32.h +++ b/src/IceTargetLoweringMIPS32.h
@@ -56,18 +56,23 @@ const char *getConstantPrefix() const final { return ""; } void emit(const ConstantUndef *C) const final { + (void)C; llvm::report_fatal_error("Not yet implemented"); } void emit(const ConstantInteger32 *C) const final { + (void)C; llvm::report_fatal_error("Not yet implemented"); } void emit(const ConstantInteger64 *C) const final { + (void)C; llvm::report_fatal_error("Not yet implemented"); } void emit(const ConstantFloat *C) const final { + (void)C; llvm::report_fatal_error("Not yet implemented"); } void emit(const ConstantDouble *C) const final { + (void)C; llvm::report_fatal_error("Not yet implemented"); } @@ -128,8 +133,8 @@ TargetDataMIPS32 &operator=(const TargetDataMIPS32 &) = delete; public: - static TargetDataLowering *create(GlobalContext *Ctx) { - return new TargetDataMIPS32(Ctx); + static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { + return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx)); } void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) const final; @@ -144,6 +149,23 @@ template <typename T> static void emitConstantPool(GlobalContext *Ctx); }; +class TargetHeaderMIPS32 final : public TargetHeaderLowering { + TargetHeaderMIPS32() = delete; + TargetHeaderMIPS32(const TargetHeaderMIPS32 &) = delete; + TargetHeaderMIPS32 &operator=(const TargetHeaderMIPS32 &) = delete; + +public: + static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) { + return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderMIPS32(Ctx)); + } + +protected: + explicit TargetHeaderMIPS32(GlobalContext *Ctx); + +private: + ~TargetHeaderMIPS32() = default; +}; + } // end of namespace Ice #endif // SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp index 90bb0e3..506b315 100644 --- a/src/IceTargetLoweringX8632.cpp +++ b/src/IceTargetLoweringX8632.cpp
@@ -5016,4 +5016,7 @@ } } +TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) + : TargetHeaderLowering(Ctx) {} + } // end of namespace Ice
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h index def9dcd..ca26fe1 100644 --- a/src/IceTargetLoweringX8632.h +++ b/src/IceTargetLoweringX8632.h
@@ -581,8 +581,8 @@ TargetDataX8632 &operator=(const TargetDataX8632 &) = delete; public: - static TargetDataLowering *create(GlobalContext *Ctx) { - return new TargetDataX8632(Ctx); + static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { + return std::unique_ptr<TargetDataLowering>(new TargetDataX8632(Ctx)); } void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) const final; @@ -597,6 +597,23 @@ template <typename T> static void emitConstantPool(GlobalContext *Ctx); }; +class TargetHeaderX8632 final : public TargetHeaderLowering { + TargetHeaderX8632() = delete; + TargetHeaderX8632(const TargetHeaderX8632 &) = delete; + TargetHeaderX8632 &operator=(const TargetHeaderX8632 &) = delete; + +public: + static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) { + return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderX8632(Ctx)); + } + +protected: + explicit TargetHeaderX8632(GlobalContext *Ctx); + +private: + ~TargetHeaderX8632() = default; +}; + } // end of namespace Ice #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632_H