Commit 9cdb5dec7a

Andrew Kelley <superjoe30@gmail.com>
2017-09-21 04:44:24
parsec: cleaner shifting code for fixed size types
1 parent a5e4e20
Changed files (4)
src/analyze.cpp
@@ -163,10 +163,6 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so
     return entry;
 }
 
-static uint8_t log2_u64(uint64_t x) {
-    return (63 - clzll(x));
-}
-
 static uint8_t bits_needed_for_unsigned(uint64_t x) {
     if (x == 0) {
         return 0;
src/parsec.cpp
@@ -347,9 +347,60 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,
     return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr);
 }
 
+static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
+    const Type *ty = qt.getTypePtr();
+    switch (ty->getTypeClass()) {
+        case Type::Builtin:
+            {
+                const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
+                switch (builtin_ty->getKind()) {
+                    case BuiltinType::Char_U:
+                    case BuiltinType::UChar:
+                    case BuiltinType::Char_S:
+                    case BuiltinType::SChar:
+                        return 8;
+                    case BuiltinType::UInt128:
+                    case BuiltinType::Int128:
+                        return 128;
+                    default:
+                        return 0;
+                }
+                zig_unreachable();
+            }
+        case Type::Typedef:
+            {
+                const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
+                const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+                const char *type_name = decl_name(typedef_decl);
+                if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
+                    return 8;
+                } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) {
+                    return 16;
+                } else if (strcmp(type_name, "uint32_t") == 0 || strcmp(type_name, "int32_t") == 0) {
+                    return 32;
+                } else if (strcmp(type_name, "uint64_t") == 0 || strcmp(type_name, "int64_t") == 0) {
+                    return 64;
+                } else {
+                    return 0;
+                }
+            }
+        default:
+            return 0;
+    }
+    zig_unreachable();
+}
+
+
 static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
         const SourceLocation &source_loc)
 {
+    uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
+    if (int_bit_width != 0) {
+        // we can perform the log2 now.
+        uint64_t cast_bit_width = log2_u64(int_bit_width);
+        return trans_create_node_symbol(c, buf_sprintf("u%" ZIG_PRI_u64, cast_bit_width));
+    }
+
     AstNode *zig_type_node = trans_qual_type(c, qt, source_loc);
 
 //    @import("std").math.Log2Int(c_long);
src/util.hpp
@@ -147,4 +147,8 @@ bool uint64_eq(uint64_t a, uint64_t b);
 uint32_t ptr_hash(const void *ptr);
 bool ptr_eq(const void *a, const void *b);
 
+static inline uint8_t log2_u64(uint64_t x) {
+    return (63 - clzll(x));
+}
+
 #endif
test/parsec.zig
@@ -315,12 +315,11 @@ pub fn addCases(cases: &tests.ParseCContext) {
         \\pub const LUA_GLOBALSINDEX = -10002;
     );
 
-    cases.add("sift right assign",
+    cases.add("shift right assign",
         \\int log2(unsigned a) {
         \\    int i = 0;
         \\    while (a > 0) {
         \\        a >>= 1;
-        \\        //i++;
         \\    }
         \\    return i;
         \\}
@@ -334,4 +333,24 @@ pub fn addCases(cases: &tests.ParseCContext) {
         \\    return i;
         \\}
     );
+
+    cases.add("shift right assign with a fixed size type",
+        \\#include <stdint.h>
+        \\int log2(uint32_t a) {
+        \\    int i = 0;
+        \\    while (a > 0) {
+        \\        a >>= 1;
+        \\    }
+        \\    return i;
+        \\}
+    ,
+        \\export fn log2(_arg_a: u32) -> c_int {
+        \\    var a = _arg_a;
+        \\    var i: c_int = 0;
+        \\    while (a > c_uint(0)) {
+        \\        a >>= u5(1);
+        \\    };
+        \\    return i;
+        \\}
+    );
 }