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