diff --git a/spec/compiler/codegen/class_spec.cr b/spec/compiler/codegen/class_spec.cr
index c6841607a9a6c11618f702bbbbb60c6ae3b24ff3..14b76c7fbbf890e7ac3d16fe656521bb4a9b2173 100755
--- a/spec/compiler/codegen/class_spec.cr
+++ b/spec/compiler/codegen/class_spec.cr
@@ -34,10 +34,6 @@ describe "Code gen: class" do
       ").to_i.should eq(42)
   end
 
-  it "codegens byte size of Int32" do
-    run("Int32.byte_size").to_i.should eq(4)
-  end
-
   it "codegens recursive type" do
     run("
       class Foo
diff --git a/spec/compiler/codegen/sizeof_spec.cr b/spec/compiler/codegen/sizeof_spec.cr
new file mode 100644
index 0000000000000000000000000000000000000000..4ce8905390549ea827b2c0c4154382783923d628
--- /dev/null
+++ b/spec/compiler/codegen/sizeof_spec.cr
@@ -0,0 +1,40 @@
+#!/usr/bin/env bin/crystal --run
+require "../../spec_helper"
+
+describe "Code gen: sizeof" do
+  it "gets sizeof int" do
+    run("sizeof(Int32)").to_i.should eq(4)
+  end
+
+  it "gets sizeof struct" do
+    run("
+      struct Foo
+        def initialize(@x, @y, @z)
+        end
+      end
+
+      Foo.new(1, 2, 3)
+
+      sizeof(Foo)
+      ").to_i.should eq(12)
+  end
+
+  it "gets sizeof class" do
+    run("
+      class Foo
+        def initialize(@x, @y, @z)
+        end
+      end
+
+      Foo.new(1, 2, 3)
+
+      sizeof(Foo)
+      ").to_i.should eq(8)
+  end
+
+  it "gets sizeof union" do
+    run("
+      sizeof(Int32 | Float64)
+      ").to_i.should eq(16)
+  end
+end
diff --git a/spec/compiler/lexer/lexer_spec.cr b/spec/compiler/lexer/lexer_spec.cr
index 6cb3e10e7041585abce45c57ee47f0de743e62af..fa1bbfdae4cf6b0e20fc3c1d2250d87340a8a0c2 100755
--- a/spec/compiler/lexer/lexer_spec.cr
+++ b/spec/compiler/lexer/lexer_spec.cr
@@ -125,7 +125,7 @@ describe "Lexer" do
   it_lexes "\t", :SPACE
   it_lexes "\n", :NEWLINE
   it_lexes "\n\n\n", :NEWLINE
-  it_lexes_keywords [:def, :if, :else, :elsif, :end, :true, :false, :class, :module, :include, :extend, :while, :nil, :do, :yield, :return, :unless, :next, :break, :begin, :lib, :fun, :type, :struct, :union, :enum, :macro, :ptr, :out, :require, :case, :when, :then, :of, :abstract, :rescue, :ensure, :is_a?, :alias, :pointerof, :ifdef, :as, :typeof]
+  it_lexes_keywords [:def, :if, :else, :elsif, :end, :true, :false, :class, :module, :include, :extend, :while, :nil, :do, :yield, :return, :unless, :next, :break, :begin, :lib, :fun, :type, :struct, :union, :enum, :macro, :ptr, :out, :require, :case, :when, :then, :of, :abstract, :rescue, :ensure, :is_a?, :alias, :pointerof, :sizeof, :ifdef, :as, :typeof]
   it_lexes_idents ["ident", "something", "with_underscores", "with_1", "foo?", "bar!", "foo$123", "foo$bar", "fooBar"]
   it_lexes_idents ["def?", "if?", "else?", "elsif?", "end?", "true?", "false?", "class?", "while?", "nil?", "do?", "yield?", "return?", "unless?", "next?", "break?", "begin?"]
   it_lexes_idents ["def!", "if!", "else!", "elsif!", "end!", "true!", "false!", "class!", "while!", "nil!", "do!", "yield!", "return!", "unless!", "next!", "break!", "begin!"]
diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr
index ea1a4c361309e7b24bf82782c9cbe91bf451392c..df7dd30c15cfbe5c726a894659273358aa1db457 100755
--- a/spec/compiler/parser/parser_spec.cr
+++ b/spec/compiler/parser/parser_spec.cr
@@ -511,6 +511,8 @@ describe "Parser" do
   it_parses "a = 1; pointerof(a)", [Assign.new("a".var, 1.int32), PointerOf.new("a".var)]
   it_parses "pointerof(@a)", PointerOf.new("@a".instance_var)
 
+  it_parses "sizeof(X)", SizeOf.new("X".path)
+
   it_parses "foo.is_a?(Const)", IsA.new("foo".call, "Const".path)
   it_parses "foo.is_a?(Foo | Bar)", IsA.new("foo".call, Union.new(["Foo".path, "Bar".path] of ASTNode))
   it_parses "foo.responds_to?(:foo)", RespondsTo.new("foo".call, "foo".symbol)
diff --git a/spec/compiler/type_inference/primitives_spec.cr b/spec/compiler/type_inference/primitives_spec.cr
index 3d47c457e91c38b7de9fd3eeb16a60f9056f7639..8df36292fca8aa4eb9908bc85d29a8711bc2416f 100755
--- a/spec/compiler/type_inference/primitives_spec.cr
+++ b/spec/compiler/type_inference/primitives_spec.cr
@@ -49,4 +49,8 @@ describe "Type inference: primitives" do
   it "types 1 + 2" do
     assert_type("1 + 2") { int32 }
   end
+
+  it "types sizeof" do
+    assert_type("sizeof(Float64)") { int32 }
+  end
 end
diff --git a/src/compiler/crystal/ast.cr b/src/compiler/crystal/ast.cr
index 80ee6c0a4c707d9ddbbd391ca4a043b6cec63999..15625290bc6ee7a49c36210351e50f9837f40a66 100644
--- a/src/compiler/crystal/ast.cr
+++ b/src/compiler/crystal/ast.cr
@@ -916,6 +916,25 @@ module Crystal
     end
   end
 
+  class SizeOf < ASTNode
+    property :exp
+
+    def initialize(@exp)
+    end
+
+    def accept_children(visitor)
+      @exp.accept visitor
+    end
+
+    def ==(other : self)
+      other.exp == exp
+    end
+
+    def clone_without_location
+      SizeOf.new(@exp.clone)
+    end
+  end
+
   class IsA < ASTNode
     property :obj
     property :const
diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr
index acbb22a7f7ae680d239036bc18143216c4e104c7..9319aaa295745cb2e5ef9535f3b40e50f94ed32a 100644
--- a/src/compiler/crystal/codegen.cr
+++ b/src/compiler/crystal/codegen.cr
@@ -196,8 +196,6 @@ module Crystal
                 codegen_primitive_pointer_realloc node, target_def, call_args
               when :pointer_add
                 codegen_primitive_pointer_add node, target_def, call_args
-              when :byte_size
-                codegen_primitive_byte_size node, target_def, call_args
               when :struct_new
                 codegen_primitive_struct_new node, target_def, call_args
               when :struct_set
@@ -466,10 +464,6 @@ module Crystal
       gep call_args[0], call_args[1]
     end
 
-    def codegen_primitive_byte_size(node, target_def, call_args)
-      llvm_size(type.instance_type)
-    end
-
     def codegen_primitive_struct_new(node, target_def, call_args)
       allocate_aggregate (node.type as PointerInstanceType).element_type
     end
@@ -856,6 +850,11 @@ module Crystal
       false
     end
 
+    def visit(node : SizeOf)
+      @last = trunc(llvm_size(node.exp.type.instance_type), LLVM::Int32)
+      false
+    end
+
     def visit(node : Include)
       @last = llvm_nil
       false
diff --git a/src/compiler/crystal/lexer.cr b/src/compiler/crystal/lexer.cr
index 9a5955aa2285309513fd9b598a13030fb5279d33..e5fdc5a3bfffaef22ba9243448d5001e9345fa3e 100644
--- a/src/compiler/crystal/lexer.cr
+++ b/src/compiler/crystal/lexer.cr
@@ -688,8 +688,15 @@ module Crystal
         end
         scan_ident(start)
       when 's'
-        if next_char == 't' && next_char == 'r' && next_char == 'u' && next_char == 'c' && next_char == 't'
-          return check_ident_or_keyword(:struct, start)
+        case next_char
+        when 'i'
+          if next_char == 'z' && next_char == 'e' && next_char == 'o' && next_char == 'f'
+            return check_ident_or_keyword(:sizeof, start)
+          end
+        when 't'
+          if next_char == 'r' && next_char == 'u' && next_char == 'c' && next_char == 't'
+            return check_ident_or_keyword(:struct, start)
+          end
         end
         scan_ident(start)
       when 't'
diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr
index 6c332e987508876532ef176d2c5f69fb04c9d192..ef5b84b11ff86eccc401b2f52a3091785ff7237d 100644
--- a/src/compiler/crystal/parser.cr
+++ b/src/compiler/crystal/parser.cr
@@ -677,6 +677,8 @@ module Crystal
           parse_alias
         when :pointerof
           parse_pointerof
+        when :sizeof
+          parse_sizeof
         when :typeof
           parse_typeof
         else
@@ -2627,6 +2629,21 @@ module Crystal
       PointerOf.new(exp)
     end
 
+    def parse_sizeof
+      next_token_skip_space
+
+      check :"("
+      next_token_skip_space_or_newline
+
+      exp = parse_single_type
+      skip_space
+
+      check :")"
+      next_token_skip_space
+
+      SizeOf.new(exp)
+    end
+
     def parse_type_def
       next_token_skip_space_or_newline
 
diff --git a/src/compiler/crystal/primitives.cr b/src/compiler/crystal/primitives.cr
index 7429d366bb748f349d9a54c1be875507eb35be28..64e4b861ea95d9a136290600efa795e639b580ad 100644
--- a/src/compiler/crystal/primitives.cr
+++ b/src/compiler/crystal/primitives.cr
@@ -11,7 +11,6 @@ module Crystal
       define_reference_primitives
       define_pointer_primitives
       define_symbol_primitives
-      define_type_sizes
       define_math_primitives
     end
 
@@ -91,13 +90,6 @@ module Crystal
       symbol.add_def Def.new("to_s", ([] of Arg), Primitive.new(:symbol_to_s))
     end
 
-    def define_type_sizes
-      byte_size = Primitive.new(:byte_size)
-      [void, self.nil, bool, char, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, symbol, reference, pointer].each do |t|
-        t.metaclass.add_def Def.new("byte_size", ([] of Arg), byte_size)
-      end
-    end
-
     def define_math_primitives
       math = types["Math"].metaclass
       math.add_def Def.new("sqrt", [Arg.new_with_type("value", float32)], Primitive.new(:math_sqrt_float32))
diff --git a/src/compiler/crystal/to_s.cr b/src/compiler/crystal/to_s.cr
index d28c0a889226a4ad17a36033233d952ca8b31431..fd845e220e6fec83c23bd2fa9fa581d746e687ef 100644
--- a/src/compiler/crystal/to_s.cr
+++ b/src/compiler/crystal/to_s.cr
@@ -761,6 +761,13 @@ module Crystal
       false
     end
 
+    def visit(node : SizeOf)
+      @str << "sizeof("
+      node.exp.accept(self)
+      @str << ")"
+      false
+    end
+
     def visit(node : IsA)
       node.obj.accept self
       @str << ".is_a?("
diff --git a/src/compiler/crystal/transformer.cr b/src/compiler/crystal/transformer.cr
index 3d53f078f558f300e4474f52e4136209b70c428c..f0ff065f2139306bffcec93a614c949829b50c9b 100644
--- a/src/compiler/crystal/transformer.cr
+++ b/src/compiler/crystal/transformer.cr
@@ -163,6 +163,11 @@ module Crystal
       node
     end
 
+    def transform(node : SizeOf)
+      node.exp = node.exp.transform(self)
+      node
+    end
+
     def transform(node : IsA)
       node.obj = node.obj.transform(self)
       node.const = node.const.transform(self)
diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr
index 4fd5d53e331721d7bcf48512ef87a34b955292d9..5ea35964181b5434994688e1727db93266936c29 100644
--- a/src/compiler/crystal/type_inference.cr
+++ b/src/compiler/crystal/type_inference.cr
@@ -885,8 +885,6 @@ module Crystal
         node.type = scope
       when :pointer_add
         node.type = scope
-      when :byte_size
-        node.type = @mod.uint64
       when :argc
         node.type = @mod.int32
       when :argv
@@ -1070,6 +1068,10 @@ module Crystal
       node.bind_to node.expressions
     end
 
+    def end_visit(node : SizeOf)
+      node.type = @mod.int32
+    end
+
     def visit(node : Rescue)
       if node_types = node.types
         types = node_types.map do |type|