From 24ffc58c2367143a1cad64e4340e0fb5e863637a Mon Sep 17 00:00:00 2001
From: "Jay Freeman (saurik)" <saurik@saurik.com>
Date: Sun, 3 Jan 2016 12:02:12 -0800
Subject: [PATCH] Add support for __int128 (though not with libffi).

---
 Analyze.cpp      |  3 +++
 Decode.cpp       | 14 ++++++++++++++
 Execute.cpp      | 20 ++++++++++++++++++++
 Output.cpp       | 10 ++++++++++
 Parser.ypp.in    | 15 ++++++++++++---
 Replace.cpp      |  4 ++++
 Scanner.lpp.in   |  1 +
 Syntax.hpp       | 14 ++++++++++++++
 sig/ffi_type.cpp | 18 ++++++++++++++++++
 sig/parse.cpp    | 19 +++++++++++++++++++
 10 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/Analyze.cpp b/Analyze.cpp
index 922dfb1..466144d 100644
--- a/Analyze.cpp
+++ b/Analyze.cpp
@@ -381,6 +381,9 @@ static void CYParseType(CXType type, CYTypedIdentifier *typed) {
         case CXType_LongLong: typed->specifier_ = $ CYTypeIntegral(CYTypeSigned, 3); break;
         case CXType_ULongLong: typed->specifier_ = $ CYTypeIntegral(CYTypeUnsigned, 3); break;
 
+        case CXType_Int128: typed->specifier_ = $ CYTypeInt128(CYTypeSigned); break;
+        case CXType_UInt128: typed->specifier_ = $ CYTypeInt128(CYTypeUnsigned); break;
+
         case CXType_BlockPointer: {
             CXType pointee(clang_getPointeeType(type));
             _assert(!clang_isFunctionTypeVariadic(pointee));
diff --git a/Decode.cpp b/Decode.cpp
index 823e6b4..819c675 100644
--- a/Decode.cpp
+++ b/Decode.cpp
@@ -56,6 +56,13 @@ CYTypedIdentifier *Primitive<signed int>::Decode(CYPool &pool) const {
     return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeSigned, 1));
 }
 
+#ifdef __SIZEOF_INT128__
+template <>
+CYTypedIdentifier *Primitive<signed __int128>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeInt128(CYTypeSigned));
+}
+#endif
+
 template <>
 CYTypedIdentifier *Primitive<signed long int>::Decode(CYPool &pool) const {
     return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeSigned, 2));
@@ -81,6 +88,13 @@ CYTypedIdentifier *Primitive<unsigned int>::Decode(CYPool &pool) const {
     return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeUnsigned, 1));
 }
 
+#ifdef __SIZEOF_INT128__
+template <>
+CYTypedIdentifier *Primitive<unsigned __int128>::Decode(CYPool &pool) const {
+    return $ CYTypedIdentifier($ CYTypeInt128(CYTypeUnsigned));
+}
+#endif
+
 template <>
 CYTypedIdentifier *Primitive<unsigned long int>::Decode(CYPool &pool) const {
     return $ CYTypedIdentifier($ CYTypeIntegral(CYTypeUnsigned, 2));
diff --git a/Execute.cpp b/Execute.cpp
index cc47fd6..36c400a 100644
--- a/Execute.cpp
+++ b/Execute.cpp
@@ -336,6 +336,11 @@ CYCastJSValue_(unsigned long int)
 CYCastJSValue_(signed long long int)
 CYCastJSValue_(unsigned long long int)
 
+#ifdef __SIZEOF_INT128__
+CYCastJSValue_(signed __int128)
+CYCastJSValue_(unsigned __int128)
+#endif
+
 JSValueRef CYJSUndefined(JSContextRef context) {
     return JSValueMakeUndefined(context);
 }
@@ -698,6 +703,11 @@ CYPoolFFI_(unsigned long int)
 CYPoolFFI_(unsigned long long int)
 CYPoolFFI_(unsigned short int)
 
+#ifdef __SIZEOF_INT128__
+CYPoolFFI_(signed __int128)
+CYPoolFFI_(unsigned __int128)
+#endif
+
 void Void::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
     _assert(false);
 }
@@ -813,6 +823,11 @@ CYFromFFI_(unsigned long int)
 CYFromFFI_(unsigned long long int)
 CYFromFFI_(unsigned short int)
 
+#ifdef __SIZEOF_INT128__
+CYFromFFI_(signed __int128)
+CYFromFFI_(unsigned __int128)
+#endif
+
 JSValueRef Void::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
     return CYJSUndefined(context);
 }
@@ -2337,6 +2352,11 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
     CYSetProperty(context, cache, CYJSString("ulong"), CYMakeType(context, sig::Primitive<unsigned long>()), kJSPropertyAttributeDontEnum);
     CYSetProperty(context, cache, CYJSString("ulonglong"), CYMakeType(context, sig::Primitive<unsigned long long>()), kJSPropertyAttributeDontEnum);
 
+#ifdef __SIZEOF_INT128__
+    CYSetProperty(context, cache, CYJSString("int128"), CYMakeType(context, sig::Primitive<__int128>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("uint128"), CYMakeType(context, sig::Primitive<unsigned __int128>()), kJSPropertyAttributeDontEnum);
+#endif
+
     CYSetProperty(context, cache, CYJSString("float"), CYMakeType(context, sig::Primitive<float>()), kJSPropertyAttributeDontEnum);
     CYSetProperty(context, cache, CYJSString("double"), CYMakeType(context, sig::Primitive<double>()), kJSPropertyAttributeDontEnum);
 
diff --git a/Output.cpp b/Output.cpp
index 06b60b2..ae441be 100644
--- a/Output.cpp
+++ b/Output.cpp
@@ -1071,6 +1071,16 @@ void CYTypeError::Output(CYOutput &out) const {
     out << "@error";
 }
 
+void CYTypeInt128::Output(CYOutput &out) const {
+    switch (signing_) {
+        case CYTypeNeutral: break;
+        case CYTypeSigned: out << "signed" << ' '; break;
+        case CYTypeUnsigned: out << "unsigned" << ' '; break;
+    }
+
+    out << "__int128";
+}
+
 void CYTypeIntegral::Output(CYOutput &out) const {
     if (signing_ == CYTypeUnsigned)
         out << "unsigned" << ' ';
diff --git a/Parser.ypp.in b/Parser.ypp.in
index 11d8d29..c2f48ce 100644
--- a/Parser.ypp.in
+++ b/Parser.ypp.in
@@ -73,6 +73,7 @@
 %union { CYParenthetical *parenthetical_; }
 %union { CYProperty *property_; }
 %union { CYPropertyName *propertyName_; }
+%union { CYTypeSigning signing_; }
 %union { CYSpan *span_; }
 %union { CYStatement *statement_; }
 %union { CYString *string_; }
@@ -424,6 +425,7 @@ type; })
 %token _goto_ "goto"
 %token _implements_ "implements"
 %token _int_ "int"
+%token ___int128_ "__int128"
 %token _interface_ "interface"
 %token _let_ "let"
 %token _let__ "!let"
@@ -677,6 +679,7 @@ type; })
 %type <typedIdentifier_> TypeSignifier
 %type <typedIdentifier_> TypeSignifierNone
 %type <typedIdentifier_> TypeSignifierOpt
+%type <signing_> TypeSigning
 %type <modifier_> ParameterTail
 %type <modifier_> TypeQualifierLeft
 %type <modifier_> TypeQualifierLeftOpt
@@ -1014,6 +1017,7 @@ IdentifierNoOf
     : IdentifierTypeNoOf
     | "char" { $$ = CYNew CYIdentifier("char"); }
     | "int" { $$ = CYNew CYIdentifier("int"); }
+    | "__int128" { $$ = CYNew CYIdentifier("__int128"); }
     | "long" { $$ = CYNew CYIdentifier("long"); }
     | "__restrict" { $$ = CYNew CYIdentifier("__restrict"); }
     | "restrict" { $$ = CYNew CYIdentifier("restrict"); }
@@ -2105,12 +2109,17 @@ StructFieldListOpt
     | { $$ = NULL; }
     ;
 
+TypeSigning
+    : { $$ = CYTypeNeutral; }
+    | "signed" { $$ = CYTypeSigned; }
+    | "unsigned" { $$ = CYTypeUnsigned; }
+    ;
+
 PrimitiveType
     : IdentifierType[name] { $$ = CYNew CYTypeVariable($name); }
     | IntegerType[pass] { $$ = $pass; }
-    | "char" { $$ = CYNew CYTypeCharacter(CYTypeNeutral); }
-    | "signed" "char" { $$ = CYNew CYTypeCharacter(CYTypeSigned); }
-    | "unsigned" "char" { $$ = CYNew CYTypeCharacter(CYTypeUnsigned); }
+    | TypeSigning[signing] "char" { $$ = CYNew CYTypeCharacter($signing); }
+    | TypeSigning[signing] "__int128" { $$ = CYNew CYTypeInt128($signing); }
     | "struct" IdentifierType[name] { $$ = CYNew CYTypeReference($name); }
     ;
 
diff --git a/Replace.cpp b/Replace.cpp
index df47604..29a78a0 100644
--- a/Replace.cpp
+++ b/Replace.cpp
@@ -1245,6 +1245,10 @@ CYTarget *CYTypeExpression::Replace(CYContext &context) {
     return typed_->Replace(context);
 }
 
+CYTarget *CYTypeInt128::Replace(CYContext &context) {
+    return $V(signing_ == CYTypeUnsigned ? "uint128" : "int128");
+}
+
 CYTarget *CYTypeIntegral::Replace(CYContext &context) {
     bool u(signing_ == CYTypeUnsigned);
     switch (length_) {
diff --git a/Scanner.lpp.in b/Scanner.lpp.in
index a928264..58cfd7d 100644
--- a/Scanner.lpp.in
+++ b/Scanner.lpp.in
@@ -482,6 +482,7 @@ XMLName {XMLNameStart}{XMLNamePart}*
 "Infinity"        L /*III*/ F(tk::_Infinity_, hi::Constant);
 "instanceof"      L /*KKK*/ F(tk::_instanceof_, hi::Operator);
 "int"             L /*FII*/ F(tk::_int_, hi::Type);
+"__int128"        L /*III*/ F(tk::___int128_, hi::Type);
 "interface"       L /*FSS*/ F(tk::_interface_, hi::Meta);
 "let"             L /*IS?*/ F(tk::_let_, hi::Meta);
 "long"            L /*FII*/ F(tk::_long_, hi::Type);
diff --git a/Syntax.hpp b/Syntax.hpp
index a0e7942..f16b877 100644
--- a/Syntax.hpp
+++ b/Syntax.hpp
@@ -2072,6 +2072,20 @@ struct CYTypeCharacter :
     virtual void Output(CYOutput &out) const;
 };
 
+struct CYTypeInt128 :
+    CYTypeSpecifier
+{
+    CYTypeSigning signing_;
+
+    CYTypeInt128(CYTypeSigning signing) :
+        signing_(signing)
+    {
+    }
+
+    virtual CYTarget *Replace(CYContext &context);
+    virtual void Output(CYOutput &out) const;
+};
+
 struct CYTypeIntegral :
     CYTypeSpecifier
 {
diff --git a/sig/ffi_type.cpp b/sig/ffi_type.cpp
index 35700e9..ab97f7a 100644
--- a/sig/ffi_type.cpp
+++ b/sig/ffi_type.cpp
@@ -24,8 +24,12 @@
 #include "sig/ffi_type.hpp"
 #include "sig/types.hpp"
 
+#if FFI_LONG_LONG_MAX == 9223372036854775807LL
 #define ffi_type_slonglong ffi_type_sint64
 #define ffi_type_ulonglong ffi_type_uint64
+#else
+#error need to configure for long long
+#endif
 
 namespace sig {
 
@@ -59,6 +63,13 @@ ffi_type *Primitive<signed int>::GetFFI(CYPool &pool) const {
     return &ffi_type_sint;
 }
 
+#ifdef __SIZEOF_INT128__
+template <>
+ffi_type *Primitive<signed __int128>::GetFFI(CYPool &pool) const {
+    _assert(false);
+}
+#endif
+
 template <>
 ffi_type *Primitive<signed long int>::GetFFI(CYPool &pool) const {
     return &ffi_type_slong;
@@ -84,6 +95,13 @@ ffi_type *Primitive<unsigned int>::GetFFI(CYPool &pool) const {
     return &ffi_type_uint;
 }
 
+#ifdef __SIZEOF_INT128__
+template <>
+ffi_type *Primitive<unsigned __int128>::GetFFI(CYPool &pool) const {
+    _assert(false);
+}
+#endif
+
 template <>
 ffi_type *Primitive<unsigned long int>::GetFFI(CYPool &pool) const {
     return &ffi_type_ulong;
diff --git a/sig/parse.cpp b/sig/parse.cpp
index b78015d..52a974d 100644
--- a/sig/parse.cpp
+++ b/sig/parse.cpp
@@ -180,6 +180,11 @@ Type *Parse_(CYPool &pool, const char **encoding, char eos, bool named, Callback
         case 's': type = new(pool) Primitive<short>(); break;
         case 'v': type = new(pool) Void(); break;
 
+#ifdef __SIZEOF_INT128__
+        case 't': type = new(pool) Primitive<signed __int128>(); break;
+        case 'T': type = new(pool) Primitive<unsigned __int128>(); break;
+#endif
+
         case '{':
             type = new(pool) Aggregate(false);
             next = '}';
@@ -282,6 +287,13 @@ const char *Primitive<signed int>::Encode(CYPool &pool) const {
     return "i";
 }
 
+#ifdef __SIZEOF_INT128__
+template <>
+const char *Primitive<signed __int128>::Encode(CYPool &pool) const {
+    return "t";
+}
+#endif
+
 template <>
 const char *Primitive<signed long int>::Encode(CYPool &pool) const {
     return "l";
@@ -307,6 +319,13 @@ const char *Primitive<unsigned int>::Encode(CYPool &pool) const {
     return "I";
 }
 
+#ifdef __SIZEOF_INT128__
+template <>
+const char *Primitive<unsigned __int128>::Encode(CYPool &pool) const {
+    return "T";
+}
+#endif
+
 template <>
 const char *Primitive<unsigned long int>::Encode(CYPool &pool) const {
     return "L";
-- 
2.47.2