diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8223c8f2d6cf8b552c37873f9ace9ebf4d9a6455..2142c8900d2f3193ff4652be4bb44e9ac509b4aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
 * Allow iterating a range in macros with `for`.
 * Use cpu cycle counter to initialize random.
 * `method_missing` now works in generic types.
+* Fixed [#154](https://github.com/manastech/crystal/issues/154): bug, constants are initialized before global variables.
 * Fixed [#168](https://github.com/manastech/crystal/issues/168): incorrect type inference of instance variables if not assigned in superclass.
 * Fixed [#169](https://github.com/manastech/crystal/issues/169): `responds_to?` wasn't working with generic types.
 * Fixed [#171](https://github.com/manastech/crystal/issues/171): ensure blocks are not executed if the rescue block returns from a def.
diff --git a/spec/compiler/codegen/const_spec.cr b/spec/compiler/codegen/const_spec.cr
index d9288c2d06376bef241fbc63a87122aae41234f8..4c631810ec5ad3d5a8dd23aadb0b383d5f332281 100644
--- a/spec/compiler/codegen/const_spec.cr
+++ b/spec/compiler/codegen/const_spec.cr
@@ -200,4 +200,12 @@ describe "Codegen: const" do
       (A + B).to_i
       ").to_i.should eq(3)
   end
+
+  it "works with const initialized after global variable" do
+    run(%(
+      $a = 1
+      COCO = $a
+      COCO
+      )).to_i.should eq(1)
+  end
 end
diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr
index 1a9f0d68f920000dd899977833dbfa6c95def64f..6ee1e2a3b6b45adf6993711a91f9c1085be4e5c1 100644
--- a/src/compiler/crystal/codegen.cr
+++ b/src/compiler/crystal/codegen.cr
@@ -129,17 +129,17 @@ module Crystal
       LLVM.set_name @argv, "argv"
 
       builder = LLVM::Builder.new
-      @builder = CrystalLLVMBuilder.new builder, self
+      @builder = wrap_builder builder
 
       @dbg_kind = LibLLVM.get_md_kind_id("dbg", 3_u32)
 
       @modules = {"" => @main_mod} of String => LLVM::Module
       @types_to_modules = {} of Type => LLVM::Module
 
-      @alloca_block, @const_block, @entry_block = new_entry_block_chain({"alloca", "const", "entry"})
+      @alloca_block, @entry_block = new_entry_block_chain({"alloca", "entry"})
       @main_alloca_block = @alloca_block
-      @const_block_entry = @const_block
 
+      @in_lib = false
       @strings = {} of StringKey => LibLLVM::ValueRef
       @symbols = {} of String => Int32
       @symbol_table_values = [] of LibLLVM::ValueRef
@@ -167,6 +167,17 @@ module Crystal
       @subprograms[@main_mod] = [fun_metadata(context.fun, MAIN_NAME, "foo.cr", 1)] if @debug
 
       alloca_vars @mod.vars, @mod
+
+      declare_const(@mod.types["ARGC_UNSAFE"] as Const)
+      declare_const(@mod.types["ARGV_UNSAFE"] as Const)
+      declare_const(@mod.types["Float32"].types["INFINITY"] as Const)
+      declare_const(@mod.types["Float64"].types["INFINITY"] as Const)
+
+      @unused_fun_defs = [] of FunDef
+    end
+
+    def wrap_builder(builder)
+      CrystalLLVMBuilder.new builder, self
     end
 
     def define_symbol_table(llvm_mod)
@@ -182,12 +193,14 @@ module Crystal
 
       # If there are no instructions in the alloca block and the
       # const block, we just removed them (less noise)
-      if LLVM.first_instruction(@alloca_block) || LLVM.first_instruction(@const_block_entry)
-        br_block_chain [@alloca_block, @const_block_entry]
-        br_block_chain [@const_block, @entry_block]
+      if LLVM.first_instruction(@alloca_block)
+        br_block_chain [@alloca_block, @entry_block]
       else
         LLVM.delete_basic_block(@alloca_block)
-        LLVM.delete_basic_block(@const_block_entry)
+      end
+
+      @unused_fun_defs.each do |node|
+        codegen_fun node.real_name, node.external, @mod, true
       end
 
       env_dump = ENV["DUMP"]?
@@ -212,8 +225,22 @@ module Crystal
     end
 
     def visit(node : FunDef)
+      if @in_lib
+        return false
+      end
+
       unless node.external.dead
-        codegen_fun node.real_name, node.external, @mod, true
+        if node.external.used
+          codegen_fun node.real_name, node.external, @mod, true
+        else
+          # If the fun is not invoked we codegen it at the end so
+          # we don't have issues with constants being used before
+          # they are declared.
+          # But, apparenty, llvm requires us to define them so that
+          # calls can find them, so we do so.
+          codegen_fun node.real_name, node.external, @mod, false
+          @unused_fun_defs << node
+        end
       end
 
       false
@@ -418,6 +445,37 @@ module Crystal
     end
 
     def visit(node : LibDef)
+      @in_lib = true
+      node.body.accept self
+      @in_lib = false
+      @last = llvm_nil
+      false
+    end
+
+    def visit(node : StructDef)
+      @last = llvm_nil
+      false
+    end
+
+    def visit(node : UnionDef)
+      @last = llvm_nil
+      false
+    end
+
+    def visit(node : EnumDef)
+      node.c_enum_type.types.each_value do |type|
+        declare_const(type as Const)
+      end
+      @last = llvm_nil
+      false
+    end
+
+    def visit(node : ExternalVar)
+      @last = llvm_nil
+      false
+    end
+
+    def visit(node : TypeDef)
       @last = llvm_nil
       false
     end
@@ -566,7 +624,10 @@ module Crystal
     def visit(node : Assign)
       target, value = node.target, node.value
 
+      # Initialize constants if they are used
       if target.is_a?(Path)
+        const = target.target_const.not_nil!
+        declare_const(const)
         @last = llvm_nil
         return false
       end
@@ -800,44 +861,7 @@ module Crystal
     def visit(node : Path)
       if const = node.target_const
         global_name = const.llvm_name
-        global = @main_mod.globals[global_name]?
-
-        unless global
-          global = @main_mod.globals.add(llvm_type(const.value.type), global_name)
-
-          if const.value.needs_const_block?
-            in_const_block("const_#{global_name}", const.container) do
-              alloca_vars const.vars
-
-              request_value do
-                accept const.value
-              end
-
-              if LLVM.constant? @last
-                LLVM.set_initializer global, @last
-                LLVM.set_global_constant global, true
-              else
-                if const.value.type.passed_by_value?
-                  @last = load @last
-                  LLVM.set_initializer global, LLVM.undef(llvm_type(const.value.type))
-                else
-                  LLVM.set_initializer global, LLVM.null(type_of @last)
-                end
-
-                store @last, global
-              end
-            end
-          else
-            old_llvm_mod = @llvm_mod
-            @llvm_mod = @main_mod
-            request_value do
-              accept const.value
-            end
-            LLVM.set_initializer global, @last
-            LLVM.set_global_constant global, true
-            @llvm_mod = old_llvm_mod
-          end
-        end
+        global = @main_mod.globals[global_name]#? || declare_const(const).not_nil!
 
         if @llvm_mod != @main_mod
           global = @llvm_mod.globals[global_name]?
@@ -861,6 +885,36 @@ module Crystal
       false
     end
 
+    def declare_const(const, global_name = const.llvm_name)
+      return nil unless const.used
+
+      global = @main_mod.globals.add(llvm_type(const.value.type), global_name)
+
+      in_const_block(const.container) do
+        alloca_vars const.vars
+
+        request_value do
+          accept const.value
+        end
+
+        if LLVM.constant? @last
+          LLVM.set_initializer global, @last
+          LLVM.set_global_constant global, true
+        else
+          if const.value.type.passed_by_value?
+            @last = load @last
+            LLVM.set_initializer global, LLVM.undef(llvm_type(const.value.type))
+          else
+            LLVM.set_initializer global, LLVM.null(type_of @last)
+          end
+
+          store @last, global
+        end
+      end
+
+      global
+    end
+
     def visit(node : Generic)
       @last = type_id(node.type)
       false
@@ -1363,7 +1417,7 @@ module Crystal
       a_fun = @main_mod.functions.add(name, arg_types, return_type) do |func|
         context.fun = func
         func.append_basic_block("entry") do |builder|
-          @builder = builder
+          @builder = wrap_builder builder
           yield func
         end
       end
@@ -1668,24 +1722,21 @@ module Crystal
 
     def in_alloca_block
       old_block = insert_block
-      if context.in_const_block
-        position_at_end @main_alloca_block
-      else
-        position_at_end @alloca_block
-      end
+      position_at_end @alloca_block
       value = yield
       position_at_end old_block
       value
     end
 
-    def in_const_block(const_block_name, container)
-      old_position = insert_block
+    def in_const_block(container)
       old_llvm_mod = @llvm_mod
+      @llvm_mod = @main_mod
+
       old_exception_handlers = @exception_handlers
+      @exception_handlers = nil
 
       with_cloned_context do
         context.fun = @main
-        context.in_const_block = true
 
         # "self" in a constant is the constant's container
         context.type = container
@@ -1693,20 +1744,7 @@ module Crystal
         # Start with fresh variables
         context.vars = LLVMVars.new
 
-        @exception_handlers = nil
-        @llvm_mod = @main_mod
-
-        const_block = new_block const_block_name
-        position_at_end const_block
-
         yield
-
-        new_const_block = insert_block
-        position_at_end @const_block
-        br const_block
-        @const_block = new_const_block
-
-        position_at_end old_position
       end
 
       @llvm_mod = old_llvm_mod
diff --git a/src/compiler/crystal/codegen/ast.cr b/src/compiler/crystal/codegen/ast.cr
index 32550a571f42088067d83e08772470887a15c7df..3fd788b734e14157286bcb7fc1fa4db67f06a03c 100644
--- a/src/compiler/crystal/codegen/ast.cr
+++ b/src/compiler/crystal/codegen/ast.cr
@@ -22,10 +22,6 @@ module Crystal
       type?.try &.no_return?
     end
 
-    def needs_const_block?
-      true
-    end
-
     def zero?
       false
     end
@@ -52,14 +48,6 @@ module Crystal
     end
   end
 
-  {% for klass in %w(Nil Bool Number Char String Symbol) %}
-    class {{klass.id}}Literal
-      def needs_const_block?
-        false
-      end
-    end
-  {% end %}
-
   class Assign
     def returns?
       value.returns?
@@ -78,17 +66,6 @@ module Crystal
     end
   end
 
-  class Primitive
-    def needs_const_block?
-      case name
-      when :float32_infinity, :flaot64_infinity
-        false
-      else
-        true
-      end
-    end
-  end
-
   class Return
     def returns?
       true
diff --git a/src/compiler/crystal/codegen/context.cr b/src/compiler/crystal/codegen/context.cr
index ec842eb9be117a925112411b97c561a624d2d415..d88485c6b2ff98d7066951d1239d6b4efcab9cdb 100644
--- a/src/compiler/crystal/codegen/context.cr
+++ b/src/compiler/crystal/codegen/context.cr
@@ -11,7 +11,6 @@ class Crystal::CodeGenVisitor < Crystal::Visitor
     property while_exit_block
     property! block
     property! block_context
-    property in_const_block
     property closure_vars
     property closure_type
     property closure_ptr
@@ -20,7 +19,6 @@ class Crystal::CodeGenVisitor < Crystal::Visitor
     property closure_self
 
     def initialize(@fun, @type, @vars = LLVMVars.new)
-      @in_const_block = false
       @closure_skip_parent = false
     end
 
@@ -51,7 +49,6 @@ class Crystal::CodeGenVisitor < Crystal::Visitor
       context.while_exit_block = @while_exit_block
       context.block = @block
       context.block_context = @block_context
-      context.in_const_block = @in_const_block
       context.closure_vars = @closure_vars
       context.closure_type = @closure_type
       context.closure_ptr = @closure_ptr
diff --git a/src/compiler/crystal/codegen/fun.cr b/src/compiler/crystal/codegen/fun.cr
index 4ddbdbf0785ab0d2374037de6909102bce76a35f..e6d5b648413968793e4c69854ad8ed5bb657ff92 100644
--- a/src/compiler/crystal/codegen/fun.cr
+++ b/src/compiler/crystal/codegen/fun.cr
@@ -46,7 +46,6 @@ class Crystal::CodeGenVisitor < Crystal::Visitor
     with_cloned_context do |old_context|
       context.type = self_type
       context.vars = LLVMVars.new
-      context.in_const_block = false
 
       @llvm_mod = fun_module
 
@@ -55,7 +54,8 @@ class Crystal::CodeGenVisitor < Crystal::Visitor
 
       args = codegen_fun_signature(mangled_name, target_def, self_type, is_fun_literal, is_closure)
 
-      if !target_def.is_a?(External) || is_exported_fun
+      needs_body = !target_def.is_a?(External) || is_exported_fun
+      if needs_body
         emit_def_debug_metadata target_def if @debug
 
         new_entry_block
@@ -122,6 +122,13 @@ class Crystal::CodeGenVisitor < Crystal::Visitor
       args.push Arg.new_with_type(block_arg.name, block_arg.type)
     end
 
+    # This is the case where we declared a fun that was not used and now we
+    # are defining its body.
+    if is_external && (existing_fun = @llvm_mod.functions[mangled_name]?)
+      context.fun = existing_fun
+      return args
+    end
+
     if is_external
       llvm_args_types = args.map { |arg| llvm_c_type(arg.type) }
       llvm_return_type = llvm_c_type(target_def.type)
diff --git a/src/compiler/crystal/normalizer.cr b/src/compiler/crystal/normalizer.cr
index 000e4cfa23e01274cb9706ad7b121a4adc114571..3b894f10ff52a43c26d972be5451cfc7a1039205 100644
--- a/src/compiler/crystal/normalizer.cr
+++ b/src/compiler/crystal/normalizer.cr
@@ -123,23 +123,13 @@ module Crystal
     #
     # From:
     #
-    #     /regex/
+    #     /regex/flags
     #
     # To:
     #
-    #     ::CONST = /regex/
-    #     CONST
+    #     Regex.new("regex", flags)
     def transform(node : RegexLiteral)
-      const_name = "#Regex_#{node.value}_#{node.modifiers}"
-      unless program.types[const_name]?
-        constructor = Call.new(Path.new(["Regex"], true), "new", [StringLiteral.new(node.value), NumberLiteral.new(node.modifiers, :i32)] of ASTNode)
-        program.types[const_name] = const = Const.new program, program, const_name, constructor, [program] of Type, program
-        @program.regexes << const
-      end
-
-      path = Path.new([const_name], true)
-      path.location = node.location
-      path
+      Call.new(Path.new(["Regex"], true), "new", [StringLiteral.new(node.value), NumberLiteral.new(node.modifiers, :i32)] of ASTNode)
     end
 
     # Convert an interpolation to a concatenation with a StringIO:
diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr
index 650ee7d889b2db615c518f8fda741feb31e3bf03..759f6f75b4c3d1ce41f5ae3764c69cffcc6798e6 100644
--- a/src/compiler/crystal/program.cr
+++ b/src/compiler/crystal/program.cr
@@ -11,7 +11,6 @@ module Crystal
 
     getter symbols
     getter global_vars
-    getter regexes
     property vars
     property literal_expander
 
@@ -20,7 +19,6 @@ module Crystal
 
       @unions = {} of Array(Int32) => Type
       @funs = {} of Array(Int32) => Type
-      @regexes = [] of Const
 
       @types["Object"] = @object = NonGenericClassType.new self, self, "Object", nil
       @object.abstract = true
@@ -54,10 +52,10 @@ module Crystal
       @float.abstract = true
 
       @types["Float32"] = @float32 = FloatType.new self, self, "Float32", @float, 4, 9
-      @float32.types["INFINITY"] = Const.new self, @float32, "FLOAT_INFINITY", Primitive.new(:float32_infinity)
+      @float32.types["INFINITY"] = Const.new self, @float32, "INFINITY", Primitive.new(:float32_infinity)
 
       @types["Float64"] = @float64 = FloatType.new self, self, "Float64", @float, 8, 10
-      @float64.types["INFINITY"] = Const.new self, @float64, "FLOAT_INFINITY", Primitive.new(:float64_infinity)
+      @float64.types["INFINITY"] = Const.new self, @float64, "INFINITY", Primitive.new(:float64_infinity)
 
       @types["Symbol"] = @symbol = SymbolType.new self, self, "Symbol", @value, 4
       @types["Pointer"] = @pointer = PointerType.new self, self, "Pointer", @value, ["T"]
diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr
index 7e4dae8929fb9b6fbd0dd457a9841281d0ccd84d..b839182fe440ebfcd83ab40b321340a517358ab2 100644
--- a/src/compiler/crystal/type_inference.cr
+++ b/src/compiler/crystal/type_inference.cr
@@ -444,9 +444,11 @@ module Crystal
 
       target.bind_to value
 
-      current_type.types[target.names.first] = Const.new(@mod, current_type, target.names.first, value, @types.dup, @scope)
+      const = Const.new(@mod, current_type, target.names.first, value, @types.dup, @scope)
+      current_type.types[target.names.first] = const
 
       node.type = @mod.nil
+      target.target_const = const
     end
 
     def type_assign(target : Global, value, node)
@@ -1432,7 +1434,7 @@ module Crystal
           constant.default_value = NumberLiteral.new(counter, enum_base_type.kind)
           counter += 1
         end
-        current_type.types[node.name] = CEnumType.new(@mod, current_type, node.name, enum_base_type, node.constants)
+        node.c_enum_type = current_type.types[node.name] = CEnumType.new(@mod, current_type, node.name, enum_base_type, node.constants)
       end
       false
     end
@@ -1505,6 +1507,7 @@ module Crystal
         end
         node.target_const = type
         node.bind_to type.value
+        type.used = true
       when Type
         node.type = check_type_in_type_args(type.remove_alias_if_simple)
       when ASTNode
diff --git a/src/compiler/crystal/type_inference/after_type_inference_transformer.cr b/src/compiler/crystal/type_inference/after_type_inference_transformer.cr
index 7abdc5048f993ad54c82c535fb68baa08c2ef1e0..4a798f1f1877eab221fe8534986b728e80d7ad7f 100644
--- a/src/compiler/crystal/type_inference/after_type_inference_transformer.cr
+++ b/src/compiler/crystal/type_inference/after_type_inference_transformer.cr
@@ -8,12 +8,6 @@ module Crystal
       transformer = AfterTypeInferenceTransformer.new(self)
       node = node.transform(transformer)
       puts node if ENV["AFTER"]? == "1"
-
-      # Make sure to transform regexes constants (see Normalizer#trnasform(Regex))
-      regexes.each do |const|
-        const.value = const.value.transform(transformer)
-      end
-
       node
     end
   end
@@ -93,6 +87,15 @@ module Crystal
     end
 
     def transform(node : Assign)
+      target = node.target
+
+      if target.is_a?(Path)
+        const = target.target_const.not_nil!
+        unless const.used
+          return node
+        end
+      end
+
       node = super
 
       # We don't want to transform constant assignments into no return
diff --git a/src/compiler/crystal/type_inference/ast.cr b/src/compiler/crystal/type_inference/ast.cr
index 008ba108c1ee7a2ea824412baa075a5a01d9705a..58f30a865780742a590ccf38954a0b9b912e5a37 100644
--- a/src/compiler/crystal/type_inference/ast.cr
+++ b/src/compiler/crystal/type_inference/ast.cr
@@ -493,5 +493,12 @@ module Crystal
   class External
     property :dead
     @dead = false
+
+    property :used
+    @used = false
+  end
+
+  class EnumDef
+    property! c_enum_type
   end
 end
diff --git a/src/compiler/crystal/type_inference/call.cr b/src/compiler/crystal/type_inference/call.cr
index 0ed42998572c720a62945560b87709160e8cb9ee..4fa530505e556a9e1ce7846c21689cf17cf884e3 100644
--- a/src/compiler/crystal/type_inference/call.cr
+++ b/src/compiler/crystal/type_inference/call.cr
@@ -360,7 +360,7 @@ module Crystal
     def recalculate_lib_call(obj_type)
       old_target_defs = @target_defs
 
-      untyped_def = obj_type.lookup_first_def(name, false) #or
+      untyped_def = obj_type.lookup_first_def(name, false)
       raise "undefined fun '#{name}' for #{obj_type}" unless untyped_def
 
       check_args_length_match obj_type, untyped_def
@@ -369,6 +369,8 @@ module Crystal
 
       check_fun_args_types_match obj_type, untyped_def
 
+      (untyped_def as External).used = true
+
       untyped_defs = [untyped_def]
       @target_defs = untyped_defs
 
diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr
index f43c62a5282cf500681b619db806539979a32508..40ac2900d5c14d3418c6c05e66a6ed936ecfcbb0 100644
--- a/src/compiler/crystal/types.cr
+++ b/src/compiler/crystal/types.cr
@@ -2564,9 +2564,11 @@ module Crystal
     getter scope_types
     getter scope
     property! vars
+    property used
 
     def initialize(program, container, name, @value, @scope_types = [] of Type, @scope = nil)
       super(program, container, name)
+      @used = false
     end
 
     def type_desc