diff --git a/environment.py b/environment.py index c8f34d1cf..30213a7d4 100644 --- a/environment.py +++ b/environment.py @@ -162,7 +162,7 @@ class CCompiler(): commands = self.get_exelist() commands.append(srcname) commands += self.get_output_flags(exename) - p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0])#, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) p.communicate() os.remove(srcname) if p.returncode != 0: @@ -188,6 +188,68 @@ int main(int argc, char **argv) { raise EnvironmentException('Could not run sizeof test binary.') return int(res.stdout) + def alignment(self, typename): + # A word of warning: this algoritm may be totally incorrect. + # However it worked for me on the cases I tried. + # There is probably a smarter and more robust way to get this + # information. + templ = '''#include + +#define TESTTYPE %s + +#define SDEF(num) struct foo##num { char pad[num]; TESTTYPE x; }; +#define PR(num) printf("%%d\\n", (int)sizeof(struct foo##num)) +SDEF(1) +SDEF(2) +SDEF(3) +SDEF(4) +SDEF(5) +SDEF(6) +SDEF(7) +SDEF(8) +SDEF(9) +SDEF(10) +SDEF(12) +SDEF(13) +SDEF(14) +SDEF(15) +SDEF(16) +SDEF(17) + +int main(int argc, char **argv) { + PR(1); + PR(2); + PR(3); + PR(4); + PR(5); + PR(6); + PR(7); + PR(8); + PR(9); + PR(10); + PR(12); + PR(13); + PR(14); + PR(15); + PR(16); + PR(17); + return 0; +} +''' + res = self.run(templ % typename) + if not res.compiled: + raise EnvironmentException('Could not compile alignment test.') + if res.returncode != 0: + raise EnvironmentException('Could not run alignment test binary.') + arr = [int(x) for x in res.stdout.split()] + for i in range(len(arr)-1): + nxt= arr[i+1] + cur = arr[i] + diff = nxt - cur + if diff > 0: + return diff + raise EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename) + def has_function(self, funcname, prefix): # This fails (returns true) if funcname is a ptr or a variable. # The correct check is a lot more difficult. diff --git a/interpreter.py b/interpreter.py index f3ac9eeb9..26c502139 100644 --- a/interpreter.py +++ b/interpreter.py @@ -652,8 +652,19 @@ class CompilerHolder(InterpreterObject): 'run' : self.run_method, 'has_function' : self.has_function_method, 'has_member' : self.has_member_method, + 'alignment' : self.alignment_method, }) + def alignment_method(self, args, kwargs): + if len(args) != 1: + raise InterpreterException('Alignment method takes exactly one positional argument.') + typename = args[0] + if not isinstance(typename, str): + raise InterpreterException('First argument is not a string.') + result = self.compiler.alignment(typename) + mlog.log('Checking for alignment of "', mlog.bold(typename), '": ', result, sep='') + return result + def run_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Run method takes exactly one positional argument.') diff --git a/test cases/common/45 alignment/meson.build b/test cases/common/45 alignment/meson.build new file mode 100644 index 000000000..703011a6e --- /dev/null +++ b/test cases/common/45 alignment/meson.build @@ -0,0 +1,13 @@ +project('alignment', 'c') + +cc = meson.get_compiler('c') + +# These tests should return the same value on all +# platforms. If (and when) they don't, fix 'em up. +if cc.alignment('char') != 1 + error('Alignment of char misdetected.') +endif + +if cc.alignment('double') != 8 + error('Alignment of double misdetected.') +endif