diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5f7d5a6463715da6564f20827865ae48944784e1..fc5a1ca68681835a6786980a175fbb8d57c4d453 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -23,3 +23,15 @@ Python 3.4 AMD CPU:
   - amd-cl-cpu
   except:
   - tags
+# PyPy AMD CPU:
+#   script:
+#   - export PY_EXE=pypy
+#   - export PYOPENCL_TEST="amd:pu"
+#   - export EXTRA_INSTALL="numpy mako"
+#   - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh
+#   - ". ./build-and-test-py-project.sh"
+#   tags:
+#   - pypy
+#   - amd-cl-cpu
+#   except:
+#   - tags
diff --git a/loopy/frontend/fortran/__init__.py b/loopy/frontend/fortran/__init__.py
index 2626069a0551a7e11c7b8703965423be8011860c..ed228ebc137d8727c7f90b7a5ce618a9bc70fb6c 100644
--- a/loopy/frontend/fortran/__init__.py
+++ b/loopy/frontend/fortran/__init__.py
@@ -82,6 +82,9 @@ def _extract_loopy_lines(source):
                 raise LoopyError("non-comment source line in loopy block")
 
             remaining_lines.append(l)
+
+            # Preserves line numbers in loopy code, for debuggability
+            loopy_lines.append("# "+l)
             continue
 
         cmt = comment_match.group(1)
@@ -92,17 +95,26 @@ def _extract_loopy_lines(source):
                 raise LoopyError("can't enter loopy block twice")
             in_loopy_code = True
 
+            # Preserves line numbers in loopy code, for debuggability
+            loopy_lines.append("# "+l)
+
         elif cmt_stripped == "$loopy end":
             if not in_loopy_code:
                 raise LoopyError("can't leave loopy block twice")
             in_loopy_code = False
 
+            # Preserves line numbers in loopy code, for debuggability
+            loopy_lines.append("# "+l)
+
         elif in_loopy_code:
             loopy_lines.append(cmt)
 
         else:
             remaining_lines.append(l)
 
+            # Preserves line numbers in loopy code, for debuggability
+            loopy_lines.append("# "+l)
+
     return "\n".join(remaining_lines), "\n".join(loopy_lines)
 
 
@@ -163,7 +175,9 @@ def parse_transformed_fortran(source, free_form=True, strict=True,
     from loopy.tools import remove_common_indentation
     transform_code = remove_common_indentation(
             transform_code,
-            require_leading_newline=False)
+            require_leading_newline=False,
+            ignore_lines_starting_with="#")
+    print(transform_code)
 
     if transform_code_context is None:
         proc_dict = {}
diff --git a/loopy/frontend/fortran/translator.py b/loopy/frontend/fortran/translator.py
index f34c69978c0b9390d7bf216f70043b472a51cc67..97005cab607f1c1db5341ca3e29bd80ec7e761c1 100644
--- a/loopy/frontend/fortran/translator.py
+++ b/loopy/frontend/fortran/translator.py
@@ -203,7 +203,6 @@ class F2LoopyTranslator(FTreeWalkerBase):
         self.auto_dependencies = auto_dependencies
 
         self.scope_stack = []
-        self.isl_context = isl.Context()
 
         self.insn_id_counter = 0
         self.condition_id_counter = 0
@@ -301,16 +300,18 @@ class F2LoopyTranslator(FTreeWalkerBase):
     TYPE_MAP = {
             ("real", "4"): np.float32,
             ("real", "8"): np.float64,
-            ("real", "16"): np.float128,
 
             ("complex", "8"): np.complex64,
             ("complex", "16"): np.complex128,
-            ("complex", "32"): np.complex256,
 
             ("integer", ""): np.int32,
             ("integer", "4"): np.int32,
-            ("complex", "8"): np.int64,
+            ("integer", "8"): np.int64,
             }
+    if hasattr(np, "float128"):
+        TYPE_MAP[("real", "16")] = np.float128
+    if hasattr(np, "complex256"):
+        TYPE_MAP[("complex", "32")] = np.complex256
 
     def dtype_from_stmt(self, stmt):
         length, kind = stmt.selector
@@ -544,7 +545,7 @@ class F2LoopyTranslator(FTreeWalkerBase):
 
         # }}}
 
-        space = isl.Space.create_from_names(self.isl_context,
+        space = isl.Space.create_from_names(isl.DEFAULT_CONTEXT,
                 set=[loopy_loop_var], params=list(loop_bound_deps))
 
         from loopy.isl_helpers import iname_rel_aff
diff --git a/loopy/isl_helpers.py b/loopy/isl_helpers.py
index 5c52988926e6714a83a620cfdad1e760fb25c4f2..2533c0f2cb16e755506124acf470ba187eb6dce4 100644
--- a/loopy/isl_helpers.py
+++ b/loopy/isl_helpers.py
@@ -359,7 +359,7 @@ def simplify_via_aff(expr):
     from loopy.symbolic import aff_from_expr, aff_to_expr, get_dependencies
     deps = get_dependencies(expr)
     return aff_to_expr(aff_from_expr(
-        isl.Space.create_from_names(isl.Context(), list(deps)),
+        isl.Space.create_from_names(isl.DEFAULT_CONTEXT, list(deps)),
         expr))
 
 
diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py
index f930df60c93b1be4df80bcfd2789c60dca1e3654..24588976a2971d16d58dba03a44035cbc494397a 100644
--- a/loopy/kernel/__init__.py
+++ b/loopy/kernel/__init__.py
@@ -266,6 +266,9 @@ class LoopKernel(RecordWithoutPickling):
                 ]:
             raise ValueError("invalid value for 'state'")
 
+        assert all(dom.get_ctx() == isl.DEFAULT_CONTEXT for dom in domains)
+        assert assumptions.get_ctx() == isl.DEFAULT_CONTEXT
+
         RecordWithoutPickling.__init__(self,
                 domains=domains,
                 instructions=instructions,
diff --git a/loopy/kernel/creation.py b/loopy/kernel/creation.py
index 1daa041c54a17214b6531751cf206878e6b1e676..70f7069bcabe87422a9cfd3752fd6fbc766fd52e 100644
--- a/loopy/kernel/creation.py
+++ b/loopy/kernel/creation.py
@@ -362,7 +362,7 @@ def _find_existentially_quantified_inames(dom_str):
     return set(ex_quant.group(1) for ex_quant in EX_QUANT_RE.finditer(dom_str))
 
 
-def parse_domains(ctx, domains, defines):
+def parse_domains(domains, defines):
     if isinstance(domains, str):
         domains = [domains]
 
@@ -381,7 +381,7 @@ def parse_domains(ctx, domains, defines):
                 dom = "[%s] -> %s" % (",".join(parameters), dom)
 
             try:
-                dom = isl.BasicSet.read_from_str(ctx, dom)
+                dom = isl.BasicSet.read_from_str(isl.DEFAULT_CONTEXT, dom)
             except:
                 print("failed to parse domain '%s'" % dom)
                 raise
@@ -1149,16 +1149,13 @@ def make_kernel(domains, instructions, kernel_data=["..."], **kwargs):
 
     # {{{ find/create isl_context
 
-    isl_context = None
     for domain in domains:
         if isinstance(domain, isl.BasicSet):
-            isl_context = domain.get_ctx()
-    if isl_context is None:
-        isl_context = isl.Context()
+            assert domain.get_ctx() == isl.DEFAULT_CONTEXT
 
     # }}}
 
-    domains = parse_domains(isl_context, domains, defines)
+    domains = parse_domains(domains, defines)
 
     arg_guesser = ArgumentGuesser(domains, instructions,
             temporary_variables, substitutions,
diff --git a/loopy/tools.py b/loopy/tools.py
index b3c610dcbcf5e23a1de5746db78d5fedc9d171ed..e734417d6095da768085fa8861c870114f071ec8 100644
--- a/loopy/tools.py
+++ b/loopy/tools.py
@@ -164,7 +164,8 @@ class PicklableDtype(object):
 
 # {{{ remove common indentation
 
-def remove_common_indentation(code, require_leading_newline=True):
+def remove_common_indentation(code, require_leading_newline=True,
+        ignore_lines_starting_with=None, strip_empty_lines=True):
     if "\n" not in code:
         return code
 
@@ -175,21 +176,43 @@ def remove_common_indentation(code, require_leading_newline=True):
         return code
 
     lines = code.split("\n")
-    while lines[0].strip() == "":
-        lines.pop(0)
-    while lines[-1].strip() == "":
-        lines.pop(-1)
-
-    if lines:
-        base_indent = 0
-        while lines[0][base_indent] in " \t":
+
+    if strip_empty_lines:
+        while lines[0].strip() == "":
+            lines.pop(0)
+        while lines[-1].strip() == "":
+            lines.pop(-1)
+
+    test_line = None
+    if ignore_lines_starting_with:
+        for l in lines:
+            strip_l = l.lstrip()
+            if (strip_l
+                    and not strip_l.startswith(ignore_lines_starting_with)):
+                test_line = l
+                break
+
+    else:
+        test_line = lines[0]
+
+    base_indent = 0
+    if test_line:
+        while test_line[base_indent] in " \t":
             base_indent += 1
 
-        for line in lines[1:]:
-            if line[:base_indent].strip():
-                raise ValueError("inconsistent indentation")
+    new_lines = []
+    for line in lines:
+        if (ignore_lines_starting_with
+                and line.lstrip().startswith(ignore_lines_starting_with)):
+            new_lines.append(line)
+            continue
+
+        if line[:base_indent].strip():
+            raise ValueError("inconsistent indentation: '%s'" % line)
+
+        new_lines.append(line[base_indent:])
 
-    return "\n".join(line[base_indent:] for line in lines)
+    return "\n".join(new_lines)
 
 # }}}
 
diff --git a/loopy/version.py b/loopy/version.py
index a33061745ab03ff06a6972742dd52674cc6f6362..31f470baec0976437ac4023b0aea55630fd661c2 100644
--- a/loopy/version.py
+++ b/loopy/version.py
@@ -25,6 +25,11 @@ VERSION = (2014, 1)
 VERSION_STATUS = ""
 VERSION_TEXT = ".".join(str(x) for x in VERSION) + VERSION_STATUS
 
-import islpy.version
+try:
+    import islpy.version
+except ImportError:
+    _islpy_version = "_UNKNOWN_"
+else:
+    _islpy_version = islpy.version.VERSION_TEXT
 
-DATA_MODEL_VERSION = "v8-islpy%s" % islpy.version.VERSION_TEXT
+DATA_MODEL_VERSION = "v9-islpy%s" % _islpy_version
diff --git a/requirements.txt b/requirements.txt
index b833d6dd0d989ad3b88aedb3d09cf21766536613..f4ce2c74cd4449717346ad04a3e2c105cad2f4d9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,7 @@
-numpy
 git+git://github.com/inducer/pytools
 git+git://github.com/inducer/islpy
 cgen
-git+git://github.com/pyopencl/pyopencl
+git+git://github.com/pyopencl/pyopencl@cffi
 git+git://github.com/inducer/pymbolic
 
 hg+https://bitbucket.org/inducer/f2py