aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--mesonbuild/compilers/c.py54
-rw-r--r--mesonbuild/interpreter.py10
-rw-r--r--test cases/common/142 compute int/config.h.in2
-rw-r--r--test cases/common/142 compute int/meson.build8
-rw-r--r--test cases/common/142 compute int/prog.c.in9
5 files changed, 65 insertions, 18 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:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index b04d586..6e3b864 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -984,20 +984,20 @@ class CompilerHolder(InterpreterObject):
check_stringlist(args)
expression = args[0]
prefix = kwargs.get('prefix', '')
- l = kwargs.get('low', -1024)
- h = kwargs.get('high', 1024)
+ low = kwargs.get('low', None)
+ high = kwargs.get('high', None)
guess = kwargs.get('guess', None)
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of compute_int must be a string.')
- if not isinstance(l, int):
+ if low is not None and not isinstance(low, int):
raise InterpreterException('Low argument of compute_int must be an int.')
- if not isinstance(h, int):
+ if high is not None and not isinstance(high, int):
raise InterpreterException('High argument of compute_int must be an int.')
if guess is not None and not isinstance(guess, int):
raise InterpreterException('Guess argument of compute_int must be an int.')
extra_args = self.determine_args(kwargs)
deps = self.determine_dependencies(kwargs)
- res = self.compiler.compute_int(expression, l, h, guess, prefix, self.environment, extra_args, deps)
+ res = self.compiler.compute_int(expression, low, high, guess, prefix, self.environment, extra_args, deps)
mlog.log('Computing int of "%s": %d' % (expression, res))
return res
diff --git a/test cases/common/142 compute int/config.h.in b/test cases/common/142 compute int/config.h.in
index ad8d077..0de63ab 100644
--- a/test cases/common/142 compute int/config.h.in
+++ b/test cases/common/142 compute int/config.h.in
@@ -1,2 +1,4 @@
#define INTSIZE @INTSIZE@
#define FOOBAR_IN_CONFIG_H @FOOBAR@
+#define MAXINT @MAXINT@
+#define MININT @MININT@
diff --git a/test cases/common/142 compute int/meson.build b/test cases/common/142 compute int/meson.build
index 43553fe..22bd266 100644
--- a/test cases/common/142 compute int/meson.build
+++ b/test cases/common/142 compute int/meson.build
@@ -7,11 +7,15 @@ cc = meson.get_compiler('c')
intsize = cc.compute_int('sizeof(int)', low : 1, high : 16, guess : 4)
foobar = cc.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc)
+maxint = cc.compute_int('INT_MAX', prefix: '#include <limits.h>')
+minint = cc.compute_int('INT_MIN', prefix: '#include <limits.h>')
cd = configuration_data()
cd.set('INTSIZE', intsize)
cd.set('FOOBAR', foobar)
cd.set('CONFIG', 'config.h')
+cd.set('MAXINT', maxint)
+cd.set('MININT', minint)
configure_file(input : 'config.h.in', output : 'config.h', configuration : cd)
s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd)
@@ -23,11 +27,15 @@ cpp = meson.get_compiler('cpp')
intsize = cpp.compute_int('sizeof(int)')
foobar = cpp.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc)
+maxint = cpp.compute_int('INT_MAX', prefix: '#include <limits.h>')
+minint = cpp.compute_int('INT_MIN', prefix: '#include <limits.h>')
cdpp = configuration_data()
cdpp.set('INTSIZE', intsize)
cdpp.set('FOOBAR', foobar)
cdpp.set('CONFIG', 'config.hpp')
+cdpp.set('MAXINT', maxint)
+cdpp.set('MININT', minint)
configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp)
spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp)
diff --git a/test cases/common/142 compute int/prog.c.in b/test cases/common/142 compute int/prog.c.in
index 3ff1463..ff1ad55 100644
--- a/test cases/common/142 compute int/prog.c.in
+++ b/test cases/common/142 compute int/prog.c.in
@@ -1,6 +1,7 @@
#include "@CONFIG@"
#include <stdio.h>
#include <wchar.h>
+#include <limits.h>
#include "foobar.h"
int main(int argc, char **argv) {
@@ -12,5 +13,13 @@ int main(int argc, char **argv) {
fprintf(stderr, "Mismatch: computed int %d, should be %d.\n", FOOBAR_IN_CONFIG_H, FOOBAR_IN_FOOBAR_H);
return 1;
}
+ if(MAXINT != INT_MAX) {
+ fprintf(stderr, "Mismatch: computed max int %d, should be %d.\n", MAXINT, INT_MAX);
+ return 1;
+ }
+ if(MININT != INT_MIN) {
+ fprintf(stderr, "Mismatch: computed min int %d, should be %d.\n", MININT, INT_MIN);
+ return 1;
+ }
return 0;
}