Index: lib/Basic/Targets.cpp |
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp |
index 3c4aa75748ba9967639bbe41e1e46f2c56d4a8b0..e71819a7327491afd9a247f7d743d807a063f398 100644 |
--- a/lib/Basic/Targets.cpp |
+++ b/lib/Basic/Targets.cpp |
@@ -252,6 +252,48 @@ public: |
} |
}; |
+// @LOCALMOD-START Emscripten |
+// Emscripten target |
+template <typename Target> |
+class EmscriptenTargetInfo : public OSTargetInfo<Target> { |
+protected: |
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, |
+ MacroBuilder &Builder) const override { |
+ // A macro for the platform. |
+ Builder.defineMacro("__EMSCRIPTEN__"); |
+ // Earlier versions of Emscripten defined this, so we continue to define it |
+ // for compatibility, for now. Users should ideally prefer __EMSCRIPTEN__. |
+ Builder.defineMacro("EMSCRIPTEN"); |
+ // A common platform macro. |
+ if (Opts.POSIXThreads) |
+ Builder.defineMacro("_REENTRANT"); |
+ // Follow g++ convention and predefine _GNU_SOURCE for C++. |
+ if (Opts.CPlusPlus) |
+ Builder.defineMacro("_GNU_SOURCE"); |
+ |
+ // Emscripten's software environment and the asm.js runtime aren't really |
+ // Unix per se, but they're perhaps more Unix-like than what software |
+ // expects when "unix" is *not* defined. |
+ DefineStd(Builder, "unix", Opts); |
+ } |
+ |
+public: |
+ explicit EmscriptenTargetInfo(const llvm::Triple &Triple) |
+ : OSTargetInfo<Target>(Triple) { |
+ // Emcripten currently does prepend a prefix to user labels, but this is |
+ // handled outside of clang. TODO: Handling this within clang may be |
+ // beneficial. |
+ this->UserLabelPrefix = ""; |
+ this->MaxAtomicPromoteWidth = this->MaxAtomicInlineWidth = 32; |
+ |
+ // Emscripten uses the Itanium ABI mostly, but it uses ARM-style pointers |
+ // to member functions so that it can avoid having to align function |
+ // addresses. |
+ this->TheCXXABI.set(TargetCXXABI::Emscripten); |
+ } |
+}; |
+// @LOCALMOD-END Emscripten |
+ |
// FreeBSD Target |
template<typename Target> |
class FreeBSDTargetInfo : public OSTargetInfo<Target> { |
@@ -5988,6 +6030,72 @@ public: |
}; |
} // end anonymous namespace. |
+// @LOCALMOD-START Emscripten |
+namespace { |
+class AsmJSTargetInfo : public TargetInfo { |
+public: |
+ explicit AsmJSTargetInfo(const llvm::Triple &T) : TargetInfo(T) { |
+ BigEndian = false; |
+ NoAsmVariants = true; |
+ LongAlign = LongWidth = 32; |
+ PointerAlign = PointerWidth = 32; |
+ IntMaxType = Int64Type = TargetInfo::SignedLongLong; |
+ DoubleAlign = 64; |
+ LongDoubleWidth = LongDoubleAlign = 64; |
+ SizeType = TargetInfo::UnsignedInt; |
+ PtrDiffType = TargetInfo::SignedInt; |
+ IntPtrType = TargetInfo::SignedInt; |
+ RegParmMax = 0; // Disallow regparm |
+ |
+ // Set the native integer widths set to just i32, since that's currently the |
+ // only integer type we can do arithmetic on without masking or splitting. |
+ // |
+ // Set the required alignment for 128-bit vectors to just 4 bytes, based on |
+ // the direction suggested here: |
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=904913#c21 |
+ // We can still set the preferred alignment to 16 bytes though. |
+ // |
+ // Set the natural stack alignment to 16 bytes to accomodate 128-bit aligned |
+ // vectors. |
+ DescriptionString = "e-p:32:32-i64:64-v128:32:128-n32-S128"; |
+ } |
+ |
+ void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {} |
+ void getTargetDefines(const LangOptions &Opts, |
+ MacroBuilder &Builder) const override { |
+ defineCPUMacros(Builder, "asmjs", /*Tuning=*/false); |
+ } |
+ void getTargetBuiltins(const Builtin::Info *&Records, |
+ unsigned &NumRecords) const override {} |
+ BuiltinVaListKind getBuiltinVaListKind() const override { |
+ // Reuse PNaCl's va_list lowering. |
+ return TargetInfo::PNaClABIBuiltinVaList; |
+ } |
+ void getGCCRegNames(const char *const *&Names, |
+ unsigned &NumNames) const override { |
+ Names = nullptr; |
+ NumNames = 0; |
+ } |
+ void getGCCRegAliases(const GCCRegAlias *&Aliases, |
+ unsigned &NumAliases) const override { |
+ Aliases = nullptr; |
+ NumAliases = 0; |
+ } |
+ bool validateAsmConstraint(const char *&Name, |
+ TargetInfo::ConstraintInfo &Info) const override { |
+ return false; |
+ } |
+ const char *getClobbers() const override { return ""; } |
+ bool isCLZForZeroUndef() const override { |
+ // Today we do clz in software, so we just do the right thing. With ES6, |
+ // we'll get Math.clz32, which is to be defined to do the right thing: |
+ // http://esdiscuss.org/topic/rename-number-prototype-clz-to-math-clz#content-36 |
+ return false; |
+ } |
+}; |
+} // end anonymous namespace. |
+// @LOCALMOD-END Emscripten |
+ |
namespace { |
class PNaClTargetInfo : public TargetInfo { |
public: |
@@ -6428,6 +6536,16 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { |
return new Mips64ELTargetInfo(Triple); |
} |
+ // @LOCALMOD-START Emscripten |
+ case llvm::Triple::asmjs: |
+ switch (os) { |
+ case llvm::Triple::Emscripten: |
+ return new EmscriptenTargetInfo<AsmJSTargetInfo>(Triple); |
+ default: |
+ return nullptr; |
+ } |
+ // @LOCALMOD-END Emscripten |
+ |
case llvm::Triple::le32: |
switch (os) { |
case llvm::Triple::NaCl: |