aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/compilers/c.py
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2018-04-06 15:57:53 -0400
committerJussi Pakkanen <jpakkane@gmail.com>2018-04-08 16:56:33 +0300
commit8a70e7cff55bd65cfd4399df878a16bbe1495782 (patch)
treebe97054053d6ada3d073d33aa99ce824b4d52426 /mesonbuild/compilers/c.py
parent23a7fe06e982fbe5d076153ef912cb3009eb1f3f (diff)
downloadmeson-8a70e7cff55bd65cfd4399df878a16bbe1495782.zip
meson-8a70e7cff55bd65cfd4399df878a16bbe1495782.tar.gz
meson-8a70e7cff55bd65cfd4399df878a16bbe1495782.tar.bz2
Remove arbitrary [-1024,1024] limit in cross_compute_int()
Copy the algorithm used by autoconf. It computes the upper and lower limits by starting at [-1,1] and multiply by 2 at each iteration. This is even faster for small numbers (the common case), for example it finds value 0 in just 2 compilations where old algorithm would check for 1024, 512, ..., 0.
Diffstat (limited to 'mesonbuild/compilers/c.py')
-rw-r--r--mesonbuild/compilers/c.py54
1 files changed, 41 insertions, 13 deletions
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 56b46b4..27cf43a 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -367,24 +367,52 @@ class CCompiler(Compiler):
return self.compiles(t.format(**fargs), env, extra_args, dependencies)
def cross_compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies):
+ # Try user's guess first
if isinstance(guess, int):
if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
return guess
- cur = low
- while low < high:
- cur = int((low + high) / 2)
- if cur == low:
- break
-
- if self._compile_int('%s >= %d' % (expression, cur), prefix, env, extra_args, dependencies):
- low = cur
+ # If no bounds are given, compute them in the limit of int32
+ maxint = 0x7fffffff
+ minint = -0x80000000
+ if not isinstance(low, int) or not isinstance(high, int):
+ if self._compile_int('%s >= 0' % (expression), prefix, env, extra_args, dependencies):
+ low = cur = 0
+ while self._compile_int('%s > %d' % (expression, cur), prefix, env, extra_args, dependencies):
+ low = cur + 1
+ if low > maxint:
+ raise EnvironmentException('Cross-compile check overflowed')
+ cur = cur * 2 + 1
+ if cur > maxint:
+ cur = maxint
+ high = cur
else:
+ low = cur = -1
+ while self._compile_int('%s < %d' % (expression, cur), prefix, env, extra_args, dependencies):
+ high = cur - 1
+ if high < minint:
+ raise EnvironmentException('Cross-compile check overflowed')
+ cur = cur * 2
+ if cur < minint:
+ cur = minint
+ low = cur
+ else:
+ # Sanity check limits given by user
+ if high < low:
+ raise EnvironmentException('high limit smaller than low limit')
+ condition = '%s <= %d && %s >= %d' % (expression, high, expression, low)
+ if not self._compile_int(condition, prefix, env, extra_args, dependencies):
+ raise EnvironmentException('Value out of given range')
+
+ # Binary search
+ while low != high:
+ cur = low + int((high - low) / 2)
+ if self._compile_int('%s <= %d' % (expression, cur), prefix, env, extra_args, dependencies):
high = cur
+ else:
+ low = cur + 1
- if self._compile_int('%s == %d' % (expression, cur), prefix, env, extra_args, dependencies):
- return cur
- raise EnvironmentException('Cross-compile check overflowed')
+ return low
def compute_int(self, expression, low, high, guess, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
@@ -416,7 +444,7 @@ class CCompiler(Compiler):
}}'''
if not self.compiles(t.format(**fargs), env, extra_args, dependencies):
return -1
- return self.cross_compute_int('sizeof(%s)' % typename, 1, 1024, None, prefix, env, extra_args, dependencies)
+ return self.cross_compute_int('sizeof(%s)' % typename, None, None, None, prefix, env, extra_args, dependencies)
def sizeof(self, typename, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
@@ -454,7 +482,7 @@ class CCompiler(Compiler):
char c;
{type} target;
}};'''
- return self.cross_compute_int('offsetof(struct tmp, target)', 1, 1024, None, t.format(**fargs), env, extra_args, dependencies)
+ return self.cross_compute_int('offsetof(struct tmp, target)', None, None, None, t.format(**fargs), env, extra_args, dependencies)
def alignment(self, typename, prefix, env, extra_args=None, dependencies=None):
if extra_args is None: