upload android base code part1

This commit is contained in:
August 2018-08-08 15:50:00 +08:00
parent e02f198e2d
commit 0a1de6c4b3
48159 changed files with 9071466 additions and 0 deletions

View file

@ -0,0 +1,7 @@
To run the libbcc lit tests:
* Ensure `llvm-rs-as` is built, either by doing a top-level `make
checkbuild` or by doing `mm` from frameworks/compile/slang.
* Ensure that LLVM and libbcc are built with
`FORCE_BUILD_LLVM_COMPONENTS=true`.
* Ensure `opt` is built from external/llvm, either by top-level `make
checkbuild` or by doing `mm` from external/llvm.

View file

@ -0,0 +1,63 @@
Summary
=======
This directory contains integration tests for debug information in libbcc.
The tests come in two flavours: host and target. Host tests are run on the
build machine (currently, only Linux has been tested extensively) and target
tests run on a live Android system (emulator or device.)
Host tests use clang to build bytecode (bc) files, which are then executed
by the libbcc driver utility (bcc) on the host through GDB. The debugger
output is verified against expected output by the llvm tool FileCheck.
Both the debugger commands and the expected output are embedded in the
original sources as comments of the form "DEBUGGER: " and "CHECK: ".
Target tests are similar, but instead of using clang, they use ant and
llvm-rs-cc from the Android SDK to build a test binary package (apk)
that is uploaded to the device (or emulator) and run with GDB attached.
The output is verified in the same way as host side tests, and the format
of the tests is the same.
*** If you are running target-side tests, you must disable parallel
*** execution with the "-j1" flag to llvm-lit
Prerequisites
=============
To run the tests, you must have built the android source tree and have
the build environment variables set (i.e. ANDROID_BUILD_TOP)
You need the following tools (not built by the android build system) on
your PATH:
- gdb (Tested with gdb 7.3 from Ubuntu 11.10)
In addition, you need a build of gdbserver available in the prebuilt directory.
Customizing
===========
By default, llvm-lit will use the clang and bcc driver built in the android
output directory. If you wish to use different versions of these tools,
set the following environment variables:
CLANG - path to clang
BCC_DRIVER - path to bcc
FILECHECK - path to FileCheck
GDB - path to GDB
Further customization is possible by modifying the lit.cfg file.
Running
=======
To execute all the tests from this directory, use the llvm-lit tool:
$ ./llvm-lit host-tests
$ ./llvm-lit target-tests -j 1
The tool can be run from any directory.
-j controls the number of tests to run in parallel
-v enables additional verbosity (useful when examining unexpected failures)
Adding new tests
================
To add new tests, just add a .c, .cpp, or .rs file to a test directory with
similar RUN/DEBUGGER/CHECK directives in comments as the existing tests.

View file

@ -0,0 +1,245 @@
#!/bin/bash -e
# Copyright 2012, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Creates and builds projects from a RenderScript testcase and a set of Java templates
HELP=no
VERBOSE=no
MINSDK=1
TARGET=1
NAME=""
OUT_DIR=
ACTIVITY=""
PACKAGE=""
SDK=""
TESTCASE_PATH=""
DRIVER=""
check_param ()
{
if [ -z "$2" ]; then
echo "ERROR: Missing parameter after option '$1'"
exit 1
fi
}
check_required_param()
{
if [ -z "$1" ]; then
echo "ERROR: Missing required parameter $2"
exit 1
fi
}
run ()
{
if [ "$VERBOSE" = "yes" ] ; then
echo "## COMMAND: $@"
fi
$@ 2>&1
}
process_template()
{
src=$1
dest=$2
sed -e "s/%ACTIVITY%/$3/g" -e "s/%PACKAGE%/$4/g" -e "s/%TESTCASE%/$5/g" -e "s/%MINSDK%/$6/g" < $src > $dest;
echo "processed $src ==> $dest"
}
while [ -n "$1" ]; do
opt="$1"
case "$opt" in
--help|-h|-\?)
HELP=yes
;;
--verbose|-v)
VERBOSE=yes
;;
--sdk)
check_param $1 $2
SDK="$2"
;;
--name)
check_param $1 $2
NAME="$2"
;;
--out)
check_param $1 $2
OUT_DIR="$2"
;;
--activity)
check_param $1 $2
ACTIVITY="$2"
;;
--package)
check_param $1 $2
PACKAGE="$2"
;;
--minsdk)
check_param $1 $2
MINSDK="$2"
;;
--target)
check_param $1 $2
TARGET="$2"
;;
--testcase)
check_param $1 $2
TESTCASE_PATH="$2"
;;
--driver)
check_param $1 $2
DRIVER="${2%/}"
;;
-*) # unknown options
echo "ERROR: Unknown option '$opt', use --help for list of valid ones."
exit 1
;;
*) # Simply record parameter
if [ -z "$PARAMETERS" ] ; then
PARAMETERS="$opt"
else
PARAMETERS="$PARAMETERS $opt"
fi
;;
esac
shift
done
if [ "$HELP" = "yes" ] ; then
echo "Usage: $PROGNAME [options]"
echo ""
echo "Build a test project from a RS testcase and a java driver template."
echo ""
echo "Required Parameters:"
echo " --sdk Location of Android SDK installation"
echo " --out <path> Location of your project directory"
echo " --testcase <name> The .rs testcase file with which to build the project"
echo " --driver <name> The java template directory with which to build the project"
echo ""
echo "Optional Parameters (reasonable defaults are used if not specified)"
echo " --activity <name> Name for your default Activity class"
echo " --package <name> Package namespace for your project"
echo " --target <name> Android build target. Execute 'android list targets' to list available targets and their ID's."
echo " --minsdk <name> minSdkVersion attribute to embed in AndroidManifest.xml of test project."
echo " --help|-h|-? Print this help"
echo " --verbose|-v Enable verbose mode"
echo ""
exit 0
fi
# Verify required parameters are non-empty
check_required_param "$SDK" "--sdk"
check_required_param "$OUT_DIR" "--out"
check_required_param "$TESTCASE_PATH" "--testcase"
check_required_param "$DRIVER" "--driver"
# Compute name of testcase
TESTCASE=`basename $TESTCASE_PATH .rs`
# Compute activity, appname, and java package, if not specified via parameters
if [ -z "$ACTIVITY" ]; then
ACTIVITY="$TESTCASE";
fi
if [ -z "$NAME" ]; then
NAME="$ACTIVITY"
fi
if [ -z "$PACKAGE" ]; then
PACKAGE=com.android.test.rsdebug.$TESTCASE
fi
# Create the project
run $SDK/tools/android create project --target $TARGET --name $NAME --path $OUT_DIR --activity $ACTIVITY --package $PACKAGE
if [ $? != 0 ] ; then
echo "ERROR: Could not create Android project."
echo " Check parameters and try again."
exit 1
fi
# Compute name of destination source directory
DEST_SRC_DIR=$OUT_DIR/src/`echo $PACKAGE | sed 's/\./\//g'`
if [ ! -d "$DRIVER" ]; then
# If driver directory does not exist, try to fix it up by searching the
# testcase directory as well
DRIVER=`dirname $TESTCASE_PATH`/"$DRIVER"
if [ ! -d $DRIVER ]; then
echo "unable to find driver in $DRIVER, please check --driver"
exit 1;
fi
fi
echo "Copying driver template from $DRIVER -> $DEST_SRC_DIR"
if [ ! -d "$DEST_SRC_DIR" ]; then
echo "Error, destination directory does not exist: $DEST_SRC_DIR";
exit 1;
fi
echo "Performing template substitutions:"
echo " %ACTIVITY% ==> $ACTIVITY"
echo " %PACKAGE% ==> $PACKAGE"
echo " %TESTCASE% ==> $TESTCASE"
echo " %MINSDK% ==> $MINSDK"
SUBST_PARAMS="$ACTIVITY $PACKAGE $TESTCASE $MINSDK"
# If it exists, use contents of driver-common directory to seed
# the testcase project
DRIVER_COMMON="`dirname $TESTCASE_PATH`/driver-common"
if [ -d $DRIVER_COMMON ]; then
echo "Found common driver directory: $DRIVER_COMMON"
ls $DRIVER_COMMON/SRC/*.java.template | while read src; do
SRC_BASENAME=`basename $src .java.template`;
dest=$DEST_SRC_DIR/`echo $SRC_BASENAME | sed "s/ACTIVITY/$ACTIVITY/g"`.java
process_template $src $dest $SUBST_PARAMS
done;
# Copy AndroidManifest.xml
COMMON_MANIFEST="$DRIVER_COMMON/AndroidManifest.xml"
if [ -e $COMMON_MANIFEST ]; then
process_template $COMMON_MANIFEST $OUT_DIR/AndroidManifest.xml $SUBST_PARAMS
fi
fi
# Copy Java source to project directory.
ls $DRIVER/*.java.template | while read src; do
SRC_BASENAME=`basename $src .java.template`
dest=$DEST_SRC_DIR/`echo $SRC_BASENAME | sed "s/ACTIVITY/$ACTIVITY/g"`.java
process_template $src $dest $SUBST_PARAMS
done;
# Copy AndroidManifest.xml override, if it exists
OVERRIDE_MANIFEST="$DRIVER/AndroidManifest.xml"
if [ -e $OVERRIDE_MANIFEST ]; then
process_template $OVERRIDE_MANIFEST $OUT_DIR/AndroidManifest.xml $SUBST_PARAMS
fi
# Copy RS testcase to project directory.
TESTCASE_DEST=$DEST_SRC_DIR/`basename $TESTCASE_PATH`
process_template $TESTCASE_PATH $TESTCASE_DEST $SUBST_PARAMS
# Buid signed and aligned apk
cd $OUT_DIR
run ant clean debug install
if [ $? != 0 ] ; then
echo "ERROR: Apk build and install failed"
exit 1
fi
exit 0

View file

@ -0,0 +1,32 @@
// RUN: %clangxx %s -O0 -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// XFAIL: host-bcc
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break aggregate-indirect-arg.cpp:22
// DEBUGGER: r
// DEBUGGER: p v
// CHECK: $1 = (SVal &)
// CHECK: Data = 0x0,
// CHECK: Kind = 2142
class SVal {
public:
~SVal() {}
const void* Data;
unsigned Kind;
};
void bar(SVal &v) {}
class A {
public:
void foo(SVal v) { bar(v); }
};
int main() {
SVal v;
v.Data = 0;
v.Kind = 2142;
A a;
a.foo(v);
return 0;
}

View file

@ -0,0 +1,30 @@
// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// Radar 9168773
// DEBUGGER: set breakpoint pending on
// DEBUGGER: b forward-declare-class.cpp:28
// DEBUGGER: r
// DEBUGGER: ptype A
// CHECK: type = class A {
// CHECK-NEXT: public:
// CHECK-NEXT: int MyData;
// CHECK-NEXT: }
class A;
class B {
public:
void foo(const A *p);
};
B iEntry;
class A {
public:
int MyData;
};
A irp;
int main() {
return 0;
}

View file

@ -0,0 +1,29 @@
// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: set verbose on
// DEBUGGER: run
// DEBUGGER: bt 2
// CHECK: function_with_a_segfault
// CHECK: some_function
static int function_with_a_segfault() {
int* bla = 0;
*bla = 5;
return 0;
}
static int some_function() {
return function_with_a_segfault();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int main() {
return bar();
}

View file

@ -0,0 +1,36 @@
// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// XFAIL: host-bcc
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break %s:34
// DEBUGGER: run
// DEBUGGER: print s
// CHECK: $1 = {d = 0.001, d2 = {10000, 100.5}}
// DEBUGGER: continue
struct double_struct {
double d;
double d2[2];
} compound_double;
float f = 0.f;
float *pf = &f;
const double d[2][2] = {{0, 1}, {2, 3.0}};
struct double_struct s;
unsigned short us = -1;
const unsigned long l = 1;
int main(int argc, char* argv[])
{
int f = 10; // shadow
s.d = 10e-4;
s.d2[0] = 1e4;
s.d2[1] = 100.5;
double result = pf[0] * d[1][1] * s.d * us * l;
return (result == 0 ? 0 : -1);
}

View file

@ -0,0 +1,43 @@
// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break %s:42
// DEBUGGER: run
// DEBUGGER: print pf[0]
// CHECK: $1 = 0
// DEBUGGER: print d[0][0]
// CHECK: $2 = 0
// DEBUGGER: print us
// CHECK: $3 = 65535
// DEBUGGER: print l
// CHECK: $4 = 1
// DEBUGGER: print f
// CHECK: $5 = 10
// DEBUGGER: continue
struct double_struct {
double d;
double d2[2];
} compound_double;
float f = 0.f;
float *pf = &f;
const double d[2][2] = {{0, 1}, {2, 3.0}};
struct double_struct s;
unsigned short us = -1;
const unsigned long l = 1;
int main(int argc, char* argv[])
{
int f = 10; // shadow
s.d = 10e-4;
s.d2[0] = 1e4;
s.d2[1] = 100.5;
double result = pf[0] * d[1][1] * s.d * us * l;
return (result == 0 ? 0 : -1);
}

View file

@ -0,0 +1,34 @@
// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break three
// DEBUGGER: run
// DEBUGGER: bt 4
// CHECK: #0
// CHECK: three () at
// CHECK: #1
// CHECK: in two
// CHECK: #2
// CHECK: in one
// CHECK: #3
// CHECK: in main
int three()
{
return 0;
}
int two()
{
return three();
}
int one()
{
return two();
}
int main(int argc, char** argv)
{
return one();
}

View file

@ -0,0 +1,66 @@
# -*- Python -*-
#
# Copyright (C) 2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
### Configuration file for target side debugger integration tests
#
# Set up the suite name, extensions that are recognized as testcases, and
# the target triple string that must be used in cases marked expected failures
config.name = 'host_bcc_debugger_integration'
config.suffixes = ['.cpp', '.c']
config.target_triple = 'host-bcc'
# If the user is running an individual tests directory, we have to load
# the libbcc site configuration first
build_top = getattr(config, 'build_top', None)
if build_top is None:
lit.load_config(config, os.path.join(os.getenv('ANDROID_BUILD_TOP',
'../../../../../'), 'frameworks', 'compile', 'libbcc', 'tests',
'debuginfo', 'lit.site.cfg'))
build_top = config.build_top
# Output directory in the android source tree
config.test_exec_root = os.path.join(config.build_top, 'out', 'host',
'tests', 'bcc-host')
#
## Set up environment variables
#
# - LD_LIBRARY_PATH for finding libbcc.so from the android build
config.environment['LD_LIBRARY_PATH'] = \
os.path.join(config.base_build_path, 'lib') + ":" + \
config.environment['LD_LIBRARY_PATH']
# - DEBUGGER and DEBUGGER_ARGS denote how to invoke the debugger
config.environment['DEBUGGER'] = config.gdb
config.environment['DEBUGGER_ARGS'] = '-q -batch -n --args ' \
+ config.bcc_driver + ' -R '
if not lit.quiet:
lit.note('using clang: %r' % config.clang)
lit.note('using bcc driver: %r' % config.bcc_driver)
lit.note('LD_LIBRARY_PATH is %r' % config.environment['LD_LIBRARY_PATH'])
# Apply host-side test macro substitutions
config.substitutions.append( ('%clangxx', ' ' + config.clang + \
' -ccc-clang-cxx -ccc-cxx ') )
config.substitutions.append( ('%extra-clang-opts', ' -emit-llvm -c ') )
config.substitutions.append( ('%clang', ' ' + config.clang + ' ') )

View file

@ -0,0 +1,46 @@
// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break %s:45
// DEBUGGER: run
// DEBUGGER: info locals
// CHECK: pf = 0x
// CHECK: s = {f = 0.00100000005, f2 = {10000, 100.5}}
// CHECK: us = 65535
// CHECK: f = 0
// CHECK: d = {{[{][{]}}0, 1}, {2, 3{{[}][}]}}
// CHECK: l = 0
// CHECK: result = 0
// DEBUGGER: continue
struct float_struct {
float f;
float f2[2];
} compound_float;
int main(int argc, char* argv[])
{
float f = 0.f;
float *pf = &f;
double d[2][2] = {{0, 1}, {2, 3.0}};
struct float_struct s;
unsigned short us = -1;
const unsigned long l = static_cast<unsigned long>(-1.0e8f);
{
int** ppn = 0;
if (ppn) {
return -1;
}
}
s.f = 10e-4f;
s.f2[0] = 1e4f;
s.f2[1] = 100.5f;
double result = pf[0] * d[1][1] * s.f * us * l;
return (result == 0 ? 0 : -1);
}

View file

@ -0,0 +1,29 @@
// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// If debug info for my_number() is emitted outside function foo's scope
// then a debugger may not be able to handle it. At least one version of
// gdb crashes in such cases.
// DEBUGGER: set breakpoint pending on
// DEBUGGER: b nested-struct.cpp:28
// DEBUGGER: run
// DEBUGGER: ptype foo
// CHECK: type = int (void)
int foo() {
struct Local {
static int my_number() {
return 42;
}
};
int i = 0;
i = Local::my_number();
return i + 1;
}
int main() {
foo();
return 0;
}

View file

@ -0,0 +1,46 @@
// RUN: %clang %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break test_parameters
// DEBUGGER: run
// DEBUGGER: step
// DEBUGGER: print pf[0]
// CHECK: $1 = 0
// DEBUGGER: print ppd[1][1]
// CHECK: $2 = 3
// DEBUGGER: print s
// CHECK: $3 = (char_struct &)
// CHECK: {c = 97 'a', c2 = "01"}
// DEBUGGER: print ppn
// CHECK: $4 = (int **) 0x0
// DEBUGGER: print us
// CHECK: $5 = 10
// DEBUGGER: print l
// CHECK: $6 = 42
// DEBUGGER: continue
struct char_struct {
char c;
char c2[2];
} compound_char;
double test_parameters(float* pf, double ppd[][2], struct char_struct& s, int** ppn = 0, unsigned short us = 10u, const unsigned long l = 42)
{
double result = pf[0] * ppd[1][1] * s.c * us * l;
return result;
}
int main(int argc, char* argv[])
{
struct char_struct s;
float f = 0.f;
double d[2][2] = {{0, 1}, {2, 3.0}};
s.c = 'a';
s.c2[0] = '0';
s.c2[1] = '1';
double result = test_parameters(&f, d, s);
return(result == 0 ? 0 : -1);
}

View file

@ -0,0 +1,75 @@
// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break function_test
// DEBUGGER: break %s:47
// DEBUGGER: break %s:55
// DEBUGGER: break %s:60
// DEBUGGER: break %s:66
// DEBUGGER: break %s:69
// DEBUGGER: run
// DEBUGGER: bt 2
// CHECK: #0
// CHECK: function_test
// CHECK: #1
// CHECK: main
// DEBUGGER: continue
// DEBUGGER: print j
// CHECK: $1 = 0
// DEBUGGER: step
// DEBUGGER: print j
// CHECK: $2 = 1
// DEBUGGER: continue
// DEBUGGER: print j
// CHECK: $3 = -1
// DEBUGGER: continue
// DEBUGGER: bt 3
// CHECK: #0
// CHECK: inline_test
// CHECK: #1
// CHECK: function_test
// CHECK: #2
// CHECK: main
// DEBUGGER: continue
// DEBUGGER: print j
// CHECK: $4 = 2
// DEBUGGER: continue
// DEBUGGER: print j
// CHECK: $5 = 0
// DEBUGGER: continue
__attribute__((noinline)) static int function_test();
__attribute__((always_inline)) static int inline_test();
int inline_test()
{
int i = 0;
i++;
return i;
}
int function_test(int c)
{
int i, j = 0;
for (i = 0; i < c; i++) {
j++;
}
{
int j = -1;
j++;
}
j += inline_test();
if (j > 0) {
j = 0;
}
return j;
}
int main(int argc, char** argv)
{
return function_test(1);
}

View file

@ -0,0 +1,37 @@
// RUN: %clangxx %s -O0 -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// XFAIL: host-bcc
// (This testcase is expected to fail because of bcc optimizations that
// are enabled by default in the absence of metadata)
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break test_struct
// DEBUGGER: run
// DEBUGGER: step
// DEBUGGER: print s
// CHECK: $1 = {n = 10, n2 = {20, 21}}
// DEBUGGER: continue
struct int_struct {
int n;
int n2[2];
} compound_int;
int test_struct(struct int_struct s)
{
s.n2[1]++;
return s.n > s.n2[0] ? s.n : s.n2[0];
}
int main(int argc, char* argv[])
{
struct int_struct s;
s.n = 10;
s.n2[0] = 20;
s.n2[1] = 21;
int result = test_struct(s);
return(result == 20 ? 0 : -1);
}

View file

@ -0,0 +1,16 @@
// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: run
// DEBUGGER: bt 2
// CHECK: function_with_a_segfault
// CHECK: main
static int function_with_a_segfault() {
int* bla = 0;
*bla = 5;
return 0;
}
int main() {
return function_with_a_segfault();
}

View file

@ -0,0 +1,31 @@
// RUN: %clangxx %s -g -fexceptions %extra-clang-opts -o %t
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: set verbose on
// DEBUGGER: b __jit_debug_register_code
// DEBUGGER: run
// DEBUGGER: info sources
// CHECK: test_info_sources.cpp
// DEBUGGER: c
static int function_with_a_segfault() {
int* bla = 0;
*bla = 5;
return 0;
}
static int some_function() {
return function_with_a_segfault();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int main() {
return bar();
}

View file

@ -0,0 +1,102 @@
# -*- Python -*-
#
# Copyright (C) 2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Configuration file for the 'lit' test runner in Android libbcc
# This file is common to both host and target side tests
import os
# Used to determine the absolute path of a tool. If env_var is set, it
# overrides the default behaviour of searching PATH for binary_name
def inferTool(lit, binary_name, env_var, PATH):
# Determine which tool to use.
tool = os.getenv(env_var)
# If the user set the overriding environment variable, use it
if tool and os.path.isfile(tool):
return tool
# Otherwise look in the path.
tool = lit.util.which(binary_name, PATH)
if not tool:
lit.fatal("couldn't find " + binary_name + " program in " + PATH + " \
, try setting " + env_var + " in your environment")
return os.path.abspath(tool)
# Get the base build directory for the android source tree from environment.
config.build_top = os.getenv('ANDROID_BUILD_TOP')
config.base_build_path = os.path.join(config.build_top, 'out', 'host',
'linux-x86')
# testFormat: The test format to use to interpret tests.
config.test_format = lit.formats.ShTest()
# Tool used to verify debugger output against expected output in source
config.filecheck = inferTool(lit, 'FileCheck', 'FILECHECK', \
os.path.join(config.base_build_path, 'bin'))
# Invokes GDB and captures output
config.test_bcc_debuginfo = inferTool(lit, 'test_bcc_debuginfo.pl', \
'TEST_JIT_DEBUGINFO', os.path.join(config.build_top, 'frameworks', \
'compile', 'libbcc', 'tests', 'debuginfo'))
# GDB
config.gdb = inferTool(lit, 'arm-linux-androideabi-gdb', 'GDB',
config.environment['PATH'])
# GDB python plugin
config.gdb_plugin = inferTool(lit, 'android-commands.py',
'ANDROID_GDB_PLUGIN', os.path.join(config.build_top, 'frameworks',
'compile', 'libbcc', 'gdb_plugin'))
config.gdb_plugin_directory = os.path.dirname(config.gdb_plugin)
# Script interpreters that are not python
config.perl = inferTool(lit, 'perl', 'PERL', config.environment['PATH'])
config.sh = inferTool(lit, 'bash', 'BASH', config.environment['PATH'])
# Tools that are specific to running host-side debugger integration tests:
config.clang = inferTool(lit, 'clang', 'CLANG',
os.path.join(config.base_build_path, 'bin')).replace('\\', '/')
config.bcc_driver = inferTool(lit, 'bcc', 'BCC_DRIVER',
os.path.join(config.base_build_path, 'obj', 'EXECUTABLES', \
'bcc_intermediates')).replace('\\', '/')
# Tools that are specific to running target-side debugger integration tests:
config.build_test_apk = inferTool(lit, 'build_test_apk.sh',
'BUILD_TEST_APK',
os.path.join(config.build_top, 'frameworks', 'compile', 'libbcc',
'tests', 'debuginfo'))
#
## Apply common substitutions
#
config.substitutions.append( ('%Test_jit_debuginfo', config.perl \
+ ' ' + config.test_bcc_debuginfo \
+ ' ' + config.filecheck + ' ' ) )
#
## Print common configuration
#
if not lit.quiet:
lit.note('using bash: %r' % config.sh)
lit.note('using perl: %r' % config.perl)
lit.note('using verification script: %r' % config.test_bcc_debuginfo)
lit.note('using FileCheck: %r' % config.filecheck)
lit.note('using GDB: %r' % config.gdb)

View file

@ -0,0 +1,26 @@
#!/usr/bin/env python
import os
import sys
# In the Android tree, use the environment variables set by envsetup.sh
# to determine correct path for the root of the source tree.
# TODO: To run clang tests, @LLVM_BINARY_DIR@ must be substituted also.
android_source_root = os.getenv('ANDROID_BUILD_TOP', ".")
llvm_source_root = os.path.join(android_source_root, 'external', 'llvm')
libbcc_source_root = os.path.join(android_source_root, 'frameworks', 'compile',
'libbcc')
# Make sure we can find the lit package.
sys.path.append(os.path.join(llvm_source_root, 'utils', 'lit'))
# Set up some builtin parameters, so that by default the LLVM test suite
# configuration file knows how to find the object tree.
builtin_parameters = {
'llvm_site_config' : os.path.join(libbcc_source_root, 'test', 'debuginfo',
'lit.site.cfg')
}
if __name__=='__main__':
import lit
lit.main(builtin_parameters)

View file

@ -0,0 +1,37 @@
// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: b entry
// DEBUGGER: run-android-app
// DEBUGGER: bt
// CHECK: entry
// CHECK: breakpoint_function.rs
#pragma version(1)
#pragma rs java_package_name(com.android.test.rsdebug.breakpoint_function)
static int twenty() {
return 20;
}
static int some_function() {
return twenty();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int root() {
return bar();
}
void entry() {
bar();
}

View file

@ -0,0 +1,41 @@
// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: b twenty
// DEBUGGER: run-android-app
// DEBUGGER: bt
// CHECK: twenty
// CHECK: some_function
// CHECK: foo
// CHECK: bar
// CHECK: entry
// CHECK: breakpoint_inlined_function.rs:
#pragma version(1)
#pragma rs java_package_name(%PACKAGE%)
static int twenty() {
return 20;
}
static int some_function() {
return twenty();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int root() {
return bar();
}
void entry() {
bar();
}

View file

@ -0,0 +1,40 @@
// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: b %s:18
// DEBUGGER: run-android-app
// DEBUGGER: bt
// CHECK: some_function
// CHECK: foo
// CHECK: bar
// CHECK: entry
// CHECK: breakpoint_inlined_sourceline.rs:
#pragma version(1)
#pragma rs java_package_name(%PACKAGE%)
static int twenty() {
return 20;
}
static int some_function() {
return twenty();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int root() {
return bar();
}
void entry() {
bar();
}

View file

@ -0,0 +1,36 @@
// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: b %s:35
// DEBUGGER: run-android-app
// DEBUGGER: bt
// CHECK: entry
#pragma version(1)
#pragma rs java_package_name(com.android.test.rsdebug.breakpoint_sourceline)
static int twenty() {
return 20;
}
static int some_function() {
return twenty();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int root() {
return bar();
}
void entry() {
bar();
}

View file

@ -0,0 +1,36 @@
// RUN: %build_test_apk --driver driver-simple --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: run-android-app
// DEBUGGER: bt
// CHECK: entry
#pragma version(1)
#pragma rs java_package_name(%PACKAGE%)
static int function_with_a_segfault() {
int* bla = 0;
*bla = 5;
return 0;
}
static int some_function() {
return function_with_a_segfault();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int root() {
return bar();
}
void entry() {
bar();
}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="%PACKAGE%"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="%MINSDK%" />
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name="%ACTIVITY%"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package %PACKAGE%;
import android.content.res.Resources;
import android.renderscript.*;
// This is the renderer for the driver
public class DriverRS {
private Resources mRes;
private RenderScriptGL mRS;
private ScriptC_%TESTCASE% mScript;
public DriverRS() {
}
// This provides us with the renderscript context and resources that
// allow us to create the script that does rendering
public void init(RenderScriptGL rs, Resources res) {
mRS = rs;
mRes = res;
initRS();
}
private void initRS() {
mScript = new ScriptC_%TESTCASE% (mRS, mRes, R.raw.%TESTCASE%);
mScript.invoke_entry();
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package %PACKAGE%;
import android.renderscript.RSSurfaceView;
import android.renderscript.RenderScriptGL;
import android.content.Context;
import android.view.MotionEvent;
public class DriverView extends RSSurfaceView {
// Renderscipt context
private RenderScriptGL mRS;
// Script that does the rendering
private DriverRS mRender;
public DriverView(Context context) {
super(context);
ensureRenderScript();
}
private void ensureRenderScript() {
if (mRS == null) {
// Initialize renderscript with desired surface characteristics.
// In this case, just use the defaults
RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
mRS = createRenderScriptGL(sc);
// Create an instance of the script that does the rendering
mRender = new DriverRS();
mRender.init(mRS, getResources());
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ensureRenderScript();
}
@Override
protected void onDetachedFromWindow() {
// Handle the system event and clean up
mRender = null;
if (mRS != null) {
mRS = null;
destroyRenderScriptGL();
}
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package %PACKAGE%;
import android.app.Activity;
import android.os.Bundle;
// Renderscript activity
public class %ACTIVITY% extends Activity {
// Custom view to use with RenderScript
private DriverView mView;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create our view and set it as the content of our Activity
mView = new DriverView(this);
setContentView(mView);
// explicit kill
this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
@Override
protected void onResume() {
// Ideally an app should implement onResume() and onPause()
// to take appropriate action when the activity loses focus
super.onResume();
mView.resume();
}
@Override
protected void onPause() {
// Ideally an app should implement onResume() and onPause()
// to take appropriate action when the activity loses focus
super.onPause();
mView.pause();
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package %PACKAGE%;
import android.content.res.Resources;
import android.renderscript.*;
// This is the renderer for the driver
public class DriverRS {
private Resources mRes;
private RenderScriptGL mRS;
private ScriptC_%TESTCASE% mScript;
public DriverRS() {
}
// This provides us with the renderscript context and resources that
// allow us to create the script that does rendering
public void init(RenderScriptGL rs, Resources res) {
mRS = rs;
mRes = res;
initRS();
}
private void initRS() {
mScript = new ScriptC_%TESTCASE% (mRS, mRes, R.raw.%TESTCASE%);
mScript.invoke_entry(40);
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package %PACKAGE%;
import android.app.Activity;
import android.os.Bundle;
// Renderscript activity
public class %ACTIVITY% extends Activity {
// Custom view to use with RenderScript
private DriverView mView;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create our view and set it as the content of our Activity
mView = new DriverView(this);
setContentView(mView);
// explicit kill
this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
@Override
protected void onResume() {
// Ideally an app should implement onResume() and onPause()
// to take appropriate action when the activity loses focus
super.onResume();
mView.resume();
}
@Override
protected void onPause() {
// Ideally an app should implement onResume() and onPause()
// to take appropriate action when the activity loses focus
super.onPause();
mView.pause();
}
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package %PACKAGE%;
import android.app.Activity;
import android.os.Bundle;
// Renderscript activity
public class %ACTIVITY% extends Activity {
// Custom view to use with RenderScript
private DriverView mView;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create our view and set it as the content of our Activity
mView = new DriverView(this);
setContentView(mView);
}
@Override
protected void onResume() {
// Ideally an app should implement onResume() and onPause()
// to take appropriate action when the activity loses focus
super.onResume();
mView.resume();
}
@Override
protected void onPause() {
// Ideally an app should implement onResume() and onPause()
// to take appropriate action when the activity loses focus
super.onPause();
mView.pause();
}
}

View file

@ -0,0 +1,48 @@
// RUN: %build_test_apk --driver driver-int-param --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: b %s:46
// DEBUGGER: run-android-app
// DEBUGGER: p global_zero
// DEBUGGER: p global_value
// CHECK: $1 = 0
// CHECK: $2 = 11
#pragma version(1)
#pragma rs java_package_name(%PACKAGE%)
// a global value
int global_zero = 0;
int global_value = 1;
static int twenty() {
return 20;
}
static int some_function() {
return twenty();
}
static int foo() {
return some_function();
}
static int bar() {
return foo();
}
int root() {
return bar();
}
void entry(int parameter) {
bar();
if (parameter != 0) {
global_value += 10;
} else {
global_zero += 1;
}
global_zero += global_value;
}

View file

@ -0,0 +1,20 @@
// RUN: %build_test_apk --driver driver-simple --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: run-android-app
// DEBUGGER: info sources
// CHECK: info_sources/info_sources.rs
#pragma version(1)
#pragma rs java_package_name(%PACKAGE%)
static int function_with_a_segfault() {
int* bla = 0;
*bla = 5;
return 0;
}
void entry() {
function_with_a_segfault();
}

View file

@ -0,0 +1,90 @@
# -*- Python -*-
#
# Copyright (C) 2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
### Configuration file for target side debugger integration tests
#
# Parameters available through lit --param options:
# android_sdk - Path to the android SDK directory
# sdk_version - SDK target to pass to 'android' for creating test projects
# minimum_sdk - SDK minimum version to embed in AndroidManifest.xml
# If the user is running an individual tests directory, we have to load
# the libbcc site configuration first
build_top = getattr(config, 'build_top', None)
if build_top is None:
lit.load_config(config, os.path.join(os.getenv('ANDROID_BUILD_TOP',
'../../../../../'), 'frameworks', 'compile', 'libbcc', 'tests',
'debuginfo', 'lit.site.cfg'))
build_top = config.build_top
# Default SDK path and version
default_sdk_dir = os.path.join(config.base_build_path, 'sdk', 'android-sdk_' \
+ os.getenv('TARGET_BUILD_VARIANT') + '.' \
+ os.getenv('USER') + '_linux-x86')
default_sdk_version = "android-JellyBean"
default_minimum_sdk = "JellyBean"
# Set up the suite name, extensions that are recognized as testcases, and
# the target triple string that must be used in cases marked expected failures
config.name = 'target_renderscript_debug'
config.suffixes = ['.rs']
config.target_triple = 'target-bcc'
# Output directory in the android source tree
if os.getenv('TARGET_BUILD_TYPE', None) == 'debug':
config.test_exec_root = os.path.join(config.build_top, 'out', 'debug',
'target', 'tests', 'rsdebug')
else:
config.test_exec_root = os.path.join(config.build_top, 'out', 'target',
'tests', 'rsdebug')
#
## Set up SDK path and version
#
config.sdk_dir = lit.params.get('android_sdk', default_sdk_dir)
if not os.path.isdir(config.sdk_dir):
lit.fatal("Android SDK directory " + config.sdk_dir + " does " \
+ "not exist. Check --param android_sdk=<path> lit parameter in test " \
+ "suite invocation.")
config.sdk_version = lit.params.get('sdk_version', default_sdk_version)
config.minimum_sdk = lit.params.get('minimum_sdk', default_minimum_sdk)
#
## Set up environment variables
#
# Propagate ANDROID_PRODUCT_OUT to child environment
config.environment['ANDROID_PRODUCT_OUT'] = os.getenv('ANDROID_PRODUCT_OUT')
config.environment['ANDROID_BUILD_TOP'] = os.getenv('ANDROID_BUILD_TOP')
config.environment['DEBUGGER'] = config.gdb
config.environment['DEBUGGER_ARGS'] = "-d " + config.gdb_plugin_directory + ' '
if not lit.quiet:
lit.note('using Android SDK: %r' % config.sdk_dir)
lit.note('using Android SDK Version: %r' % config.sdk_version)
lit.note('using test apk builder: %r' % config.build_test_apk)
lit.note('using GDB plugin directory: %r' % config.gdb_plugin_directory)
# Apply target-side test macro substitutions
config.substitutions.append( ('%build_test_apk_opts', ' --sdk ' + config.sdk_dir \
+ ' --target ' + config.sdk_version \
+ ' --minsdk ' + config.minimum_sdk))
config.substitutions.append( ('%build_test_apk', ' ' + config.sh \
+ ' ' + config.build_test_apk + ' '))

View file

@ -0,0 +1,57 @@
// RUN: %build_test_apk --driver driver-simple-exit --out %t --testcase %s %build_test_apk_opts
// RUN: %Test_jit_debuginfo %s %t
// DEBUGGER: source android-commands.py
// DEBUGGER: load-android-app %t
// DEBUGGER: set breakpoint pending on
// DEBUGGER: break locals.rs:48
// DEBUGGER: run-android-app
// DEBUGGER: info locals
// CHECK: pf = 0x
// CHECK: s = {f = 0.00100000005, f2 = {10000, 100.5}}
// CHECK: us = 65535
// CHECK: f = 0
// CHECK: d = {{[{][{]}}0, 1}, {2, 3{{[}][}]}}
// CHECK: l = 0
// CHECK: result = 0
// DEBUGGER: continue
struct float_struct {
float f;
float f2[2];
} compound_float;
static
int main(int argc, char* argv[])
{
float f = 0.f;
float *pf = &f;
double d[2][2] = {{0, 1}, {2, 3.0}};
struct float_struct s;
unsigned short us = -1;
const unsigned long l = (unsigned long) -1.0e8f;
{
int** ppn = 0;
if (ppn) {
return -1;
}
}
s.f = 10e-4f;
s.f2[0] = 1e4f;
s.f2[1] = 100.5f;
double result = pf[0] * d[1][1] * s.f * us * l;
return (result == 0 ? 0 : -1);
}
void entry() {
main(0, 0);
}
#pragma version(1)
#pragma rs java_package_name(%PACKAGE%)

View file

@ -0,0 +1,90 @@
#!/usr/bin/perl
#===-- test_bcc_debuginfo.pl - Debugger integration test driver script ---===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===----------------------------------------------------------------------===#
#
# This script tests debugging information generated by a compiler.
# Input arguments
# - Path to FileCheck tool.
# - Input source program. Usually this source file is decorated using
# special comments (//DEBUGGER:, //CHECK:)to communicate debugger commands.
# - Executable file. This file is generated by the compiler.
#
# This perl script extracts debugger commands from input source program
# comments in a script. A debugger is used to load the executable file
# and run the script generated from source program comments. Finally,
# the debugger output is checked, using FileCheck, to validate
# debugging information.
#
#===----------------------------------------------------------------------===#
use File::Basename;
my $filecheck_tool = $ARGV[0];
my $testcase_file = $ARGV[1];
my $testcase_output = $ARGV[2];
my $input_filename = basename $testcase_file;
my $output_dir = dirname $testcase_output;
my $debugger_script_file = "$output_dir/$input_filename.debugger.script";
my $output_file = "$output_dir/$input_filename.gdb.output";
open(OUTPUT, ">$debugger_script_file");
# Enable extra verbosity in GDB
print OUTPUT "set verbose on\n";
# Extract debugger commands from testcase. They are marked with DEBUGGER:
# at the beginning of a comment line.
open(INPUT, $testcase_file);
while(<INPUT>) {
my($line) = $_;
$i = index($line, "DEBUGGER:");
if ( $i >= 0) {
$l = length("DEBUGGER:");
$s = substr($line, $i + $l);
$s =~ s/\%s/$input_filename/g;
$s =~ s/\%t/$testcase_output/g;
print OUTPUT "$s";
}
}
print OUTPUT "\n";
print OUTPUT "quit\n";
close(INPUT);
close(OUTPUT);
# setup debugger and debugger options to run a script.
my $debugger = $ENV{'DEBUGGER'};
my $debugger_options = $ENV{'DEBUGGER_ARGS'};
if (!$debugger) {
print "Please set DEBUGGER prior to using this script";
exit 1;
}
$debugger_options = "-x $debugger_script_file $debugger_options $testcase_output";
# run debugger and capture output.
system("$debugger $debugger_options > $output_file 2>&1") ;
if ($?>>8 != 0) {
print "Error during debugger invocation. Command used was: \n";
print("$debugger $debugger_options > $output_file 2>&1\n") ;
exit 1;
}
# validate output.
system("$filecheck_tool", "-input-file", "$output_file", "$testcase_file");
if ($?>>8 != 0) {
print "Error during verification. Debugger command used was: \n";
print("$debugger $debugger_options > $output_file 2>&1\n") ;
print "Verification command used was: \n";
print "$filecheck_tool -input-file $output_file $testcase_file\n";
exit 1;
}
else {
exit 0;
}

View file

@ -0,0 +1,45 @@
; Per https://llvm.org/bugs/show_bug.cgi?id=26619, check that for DIGlobalVariable of floating-point type,
; we emit its constant value (if any) in debug info.
; Debug metadata doesn't survive passage through llvm-rs-as. Therefore, we represent
; the test case as a separate bitcode file, rather than as the ASCII IR in this file.
; There doesn't seem to be any way to compute the basename of %s, hence the unfortunate
; explicit uses of "debug_info_static_const_fp" below.
; RUN: bcc -o debug_info_static_const_fp -output_path %T -bclib libclcore.bc -mtriple armv7-none-linux-gnueabi %S/debug_info_static_const_fp.bc
; RUN: llvm-dwarfdump -debug-dump=info %T/debug_info_static_const_fp.o | FileCheck %s
; 32-bit bitcode compiled from the following (-O0 -g):
;
; #pragma version(1)
; #pragma rs java_package_name(debug_info_static_const_fp)
;
; static const __fp16 hVal = 29/13.0f; // 2.2307692307692307692 (2.23046875)
;
; static const float fVal = -147/17.0f; // -8.6470588235294117647 (-8.64705849)
;
; static const double dVal = 19637/7.0; // 2805.2857142857142857 (2805.2857142857142)
;
; int iVal;
;
; void compute() {
; iVal = hVal + fVal + dVal;
; }
; CHECK: DW_TAG_variable
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_name {{.*}} "hVal"
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_const_value {{.*}} (16502)
; CHECK: DW_TAG_variable
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_name {{.*}} "fVal"
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_const_value {{.*}} (3238681178)
; CHECK: DW_TAG_variable
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_name {{.*}} "dVal"
; CHECK-NOT: {{DW_TAG|NULL}}
; CHECK: DW_AT_const_value {{.*}} (4658387303597904457)

View file

@ -0,0 +1,77 @@
; This checks that RSForEachExpand generates getelementptr
; instructions into the driver info structure as expected - namely,
; that they index into the right positions of the structure and that
; the instructions that are generated are in the loop header.
; RUN: opt -load libbcc.so -kernelexp -S < %s | FileCheck %s
; ModuleID = 'test_getelementptr.bc'
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-none-linux-gnueabi"
; Declarations expected by the expansion pass.
declare void @_Z14rsGetElementAt13rs_allocationj()
declare void @_Z14rsGetElementAt13rs_allocationjj()
declare void @_Z14rsGetElementAt13rs_allocationjjj()
declare void @_Z14rsSetElementAt13rs_allocationPvj()
declare void @_Z14rsSetElementAt13rs_allocationPvjj()
declare void @_Z14rsSetElementAt13rs_allocationPvjjj()
declare void @_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj()
declare void @_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj()
declare void @_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj()
; Old-style kernel
define void @root(i32* nocapture %ain, i32* nocapture %out, i32 %x, i32 %y, i32 %z) {
ret void
; CHECK: define void @root.expand(%RsExpandKernelDriverInfoPfx* %p, i32 %x1, i32 %x2, i32 %outstep)
; CHECK: Begin:
; CHECK: %instep_addr.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 1, i32 0
; CHECK: load i32, i32* %instep_addr.gep
; CHECK: %input_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 0, i32 0
; CHECK: load i8*, i8** %input_buf.gep
; CHECK: %out_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 3, i32 0
; CHECK: load i8*, i8** %out_buf.gep
; CHECK: %Y.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 1
; CHECK: load i32, i32* %Y.gep
; CHECK: %Z.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 2
; CHECK: load i32, i32* %Z.gep
; CHECK: Loop:
}
; New style kernel with multiple inputs
define i32 @foo(i32 %in0, i32 %in1, i32 %x, i32 %y, i32 %z) {
ret i32 0
; CHECK: define void @foo.expand(%RsExpandKernelDriverInfoPfx* %p, i32 %x1, i32 %x2, i32 %arg_outstep)
; CHECK: Begin:
; CHECK: %out_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 3, i32 0
; CHECK: load i8*, i8** %out_buf.gep
; CHECK: %Y.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 1
; CHECK: load i32, i32* %Y.gep
; CHECK: %Z.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 7, i32 2
; CHECK: load i32, i32* %Z.gep
; CHECK: %input_buf.gep = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 0, i32 0
; CHECK: load i8*, i8** %input_buf.gep
; CHECK: %input_buf.gep1 = getelementptr inbounds %RsExpandKernelDriverInfoPfx, %RsExpandKernelDriverInfoPfx* %p, i32 0, i32 0, i32 1
; CHECK: load i8*, i8** %input_buf.gep1
; CHECK: Loop:
}
!llvm.ident = !{!0}
!\23pragma = !{!1, !2}
!\23rs_export_foreach_name = !{!3, !4}
!\23rs_export_foreach = !{!5, !6}
; The following named metadata would not be present in a bitcode file,
; but instead synthesized by bcc from the bitcode wrapper. However,
; for this test case, we're not running bcc, but instead opt, and so
; we never get the opportunity to synthesize this named metadata.
!\23rs_wrapper = !{!7}
!0 = !{!"clang version 3.6 "}
!1 = !{!"version", !"1"}
!2 = !{!"java_package_name", !"foo"}
!3 = !{!"root"}
!4 = !{!"foo"}
!5 = !{!"91"}
!6 = !{!"123"}
!7 = !{!"0", !"3"}

View file

@ -0,0 +1,61 @@
# -*- Python -*-
# Configuration file for the 'lit' test runner.
import subprocess
import re
# name: The name of this test suite.
config.name = 'libbcc'
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.ll']
# testFormat: The test format to use to interpret tests.
import lit.formats
config.test_format = lit.formats.ShTest()
ANDROID_HOST_OUT = os.getenv("ANDROID_HOST_OUT")
ANDROID_PRODUCT_OUT = os.getenv("ANDROID_PRODUCT_OUT")
if not ANDROID_HOST_OUT or not ANDROID_PRODUCT_OUT:
import sys
sys.exit(1)
# test_source_root: The path where tests are located (default is the test suite
# root).
config.test_source_root = None
config.test_exec_root = os.path.join(ANDROID_HOST_OUT, 'tests', 'libbcc')
tools_dir = os.pathsep.join([os.path.join(ANDROID_HOST_OUT, 'bin'),
os.path.join(ANDROID_HOST_OUT, 'lib64'),
os.path.join(ANDROID_PRODUCT_OUT, 'system/lib')])
# Based on LLVM's lit.cfg: "For each occurrence of an llvm tool name
# as its own word, replace it with the full path to the build directory
# holding that tool."
for pattern in [r"\bFileCheck\b",
r"\bllvm-rs-as\b",
r"\bbcinfo\b",
r"\bopt\b",
r"\blibbcc.so\b",
r"\bllvm-objdump\b",
r"\bbcc\b",
r"\blibclcore.bc\b"]:
tool_match = re.match(r"^(\\)?((\| )?)\W+b([\.0-9A-Za-z-_]+)\\b\W*$",
pattern)
tool_pipe = tool_match.group(2)
tool_name = tool_match.group(4)
import lit.util
tool_path = lit.util.which(tool_name, tools_dir)
if not tool_path:
lit_config.note("Did not find " + tool_name + " in " + tools_dir)
tool_path = os.path.join(tools_dir, tool_name)
config.substitutions.append((pattern, tool_pipe + tool_path))
# The following substitution is needed for the versioninfo tests
llvm_version_string = subprocess.check_output([
lit.util.which('llvm-config', tools_dir),
'--version'
]).strip()
config.substitutions.append(('%LLVM_VERSION_STRING', llvm_version_string))

View file

@ -0,0 +1,78 @@
; This test checks that the code doesn't aggressively apply TBAA
; metadata to temporaries that are passed by pointer to kernels.
; RUN: opt -load libbcc.so -kernelexp -inline -tbaa -aa-eval -print-may-aliases -evaluate-aa-metadata < %s -S -o - 2>&1 | FileCheck %s
; ModuleID = 'kernel.bc'
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-none-linux-gnueabi"
; Declarations expected by the expansion pass.
declare void @_Z14rsGetElementAt13rs_allocationj()
declare void @_Z14rsGetElementAt13rs_allocationjj()
declare void @_Z14rsGetElementAt13rs_allocationjjj()
declare void @_Z14rsSetElementAt13rs_allocationPvj()
declare void @_Z14rsSetElementAt13rs_allocationPvjj()
declare void @_Z14rsSetElementAt13rs_allocationPvjjj()
declare void @_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj()
declare void @_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj()
declare void @_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj()
%struct.int5.0 = type { [5 x i32] }
; Function Attrs: nounwind
define void @add1_int5(%struct.int5.0* noalias nocapture sret %agg.result, %struct.int5.0* nocapture %in) #0 {
br label %1
; <label>:1 ; preds = %1, %0
%indvars.iv = phi i64 [ 0, %0 ], [ %indvars.iv.next, %1 ]
%2 = getelementptr inbounds %struct.int5.0, %struct.int5.0* %in, i64 0, i32 0, i64 %indvars.iv
; CHECK: MayAlias: %load_from_input{{.*}} <-> store %struct.int5.0 %input, %struct.int5.0* %input_struct_slot
%load_from_input = load i32, i32* %2, align 4, !tbaa !9
%3 = add nsw i32 %load_from_input, 1
store i32 %3, i32* %2, align 4, !tbaa !9
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%exitcond = icmp eq i64 %indvars.iv.next, 5
br i1 %exitcond, label %4, label %1
; <label>:4 ; preds = %1
%5 = bitcast %struct.int5.0* %agg.result to i8*
%6 = bitcast %struct.int5.0* %in to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* %6, i64 20, i32 4, i1 false), !tbaa.struct !13
ret void
}
; Function Attrs: nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
attributes #0 = { nounwind }
!llvm.ident = !{!0}
!\23pragma = !{!1, !2}
!\23rs_export_foreach_name = !{!3, !4}
!\23rs_export_foreach = !{!5, !6}
!\23rs_export_type = !{!7}
!\25int5 = !{!8}
; The following named metadata would not be present in a bitcode file,
; but instead synthesized by bcc from the bitcode wrapper. However,
; for this test case, we're not running bcc, but instead opt, and so
; we never get the opportunity to synthesize this named metadata.
!\23rs_wrapper = !{!15}
!0 = !{!"clang version 3.6 "}
!1 = !{!"version", !"1"}
!2 = !{!"java_package_name", !"foo"}
!3 = !{!"root"}
!4 = !{!"add1_int5"}
!5 = !{!"0"}
!6 = !{!"35"}
!7 = !{!"int5"}
!8 = !{!"data", !"<ConstantArray>"}
!9 = !{!10, !10, i64 0}
!10 = !{!"int", !11, i64 0}
!11 = !{!"omnipotent char", !12, i64 0}
!12 = !{!"Simple C/C++ TBAA"}
!13 = !{i64 0, i64 20, !14}
!14 = !{!11, !11, i64 0}
!15 = !{!"0", !"3"}

View file

@ -0,0 +1,50 @@
; Basic test of TBAA that should report that pointer loads do not
; alias with stores to allocations.
; RUN: opt -load libbcc.so -kernelexp -tbaa -aa-eval -print-no-aliases -evaluate-aa-metadata < %s -S -o - 2>&1 | FileCheck %s
; ModuleID = 'kernel.bc'
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-none-linux-gnueabi"
; Declarations expected by the expansion pass.
declare void @_Z14rsGetElementAt13rs_allocationj()
declare void @_Z14rsGetElementAt13rs_allocationjj()
declare void @_Z14rsGetElementAt13rs_allocationjjj()
declare void @_Z14rsSetElementAt13rs_allocationPvj()
declare void @_Z14rsSetElementAt13rs_allocationPvjj()
declare void @_Z14rsSetElementAt13rs_allocationPvjjj()
declare void @_Z25rsGetElementAtYuv_uchar_Y13rs_allocationjj()
declare void @_Z25rsGetElementAtYuv_uchar_U13rs_allocationjj()
declare void @_Z25rsGetElementAtYuv_uchar_V13rs_allocationjj()
; CHECK: NoAlias: %0 = load {{.*}}, i8** %out_buf.gep, !tbaa {{.*}} <-> store i32 %call.result, i32* {{.*}}, !tbaa {{.*}}
; CHECK: NoAlias: %input_buf = load i8*, i8** %input_buf.gep, !tbaa {{.*}} <-> store i32 %call.result, i32* {{.*}}, !tbaa {{.*}}
; Function Attrs: nounwind readnone
define i32 @add1(i32 %in) #0 {
%1 = add nsw i32 %in, 1
ret i32 %1
}
attributes #0 = { nounwind readnone }
!llvm.ident = !{!0}
!\23pragma = !{!1, !2}
!\23rs_export_foreach_name = !{!3, !4}
!\23rs_export_foreach = !{!5, !6}
; The following named metadata would not be present in a bitcode file,
; but instead synthesized by bcc from the bitcode wrapper. However,
; for this test case, we're not running bcc, but instead opt, and so
; we never get the opportunity to synthesize this named metadata.
!\23rs_wrapper = !{!7}
!0 = !{!"clang version 3.6 "}
!1 = !{!"version", !"1"}
!2 = !{!"java_package_name", !"foo"}
!3 = !{!"root"}
!4 = !{!"add1"}
!5 = !{!"0"}
!6 = !{!"35"}
!7 = !{!"0", !"3"}

View file

@ -0,0 +1,355 @@
; Check that the unexpanded accumulator functions and the dummy variables are deleted.
; There doesn't seem to be any way to compute the basename of %s, hence the unfortunate
; explicit uses of "test_reduce_general_cleanup" below.
; There doesn't seem to be a way to write a CHECK-NOT pattern that matches only at the
; end of a line (llvm-objdump dumps symbol name at end of line), so sed is employed
; to add a '<' at the end of each line (symbol name). This allows us to use (e.g.)
; "aiAccum<" to match the symbol "aiAccum" but not the symbol "aiAccum.expand".
; RUN: llvm-rs-as %s -o %t
; RUN: bcc -o test_reduce_general_cleanup -output_path %T -bclib libclcore.bc -mtriple armv7-none-linux-gnueabi %t
; RUN: llvm-objdump -t %T/test_reduce_general_cleanup.o | sed -e 's!$!<!' | FileCheck %s
; CHECK-NOT: .rs.reduce_fn
; CHECK-NOT: aiAccum<
; CHECK-NOT: mpyAccum<
; CHECK-NOT: dpAccum<
; CHECK-NOT: fMMAccumulator<
; CHECK-NOT: fzAccum<
; CHECK-NOT: fz2Accum<
; CHECK-NOT: hsgAccum<
; ModuleID = 'reduce.bc'
target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
target triple = "armv7-none-linux-gnueabi"
%struct.MinAndMax = type { %struct.IndexedVal, %struct.IndexedVal }
%struct.IndexedVal = type { float, i32 }
@.rs.reduce_fn.aiAccum = global i8* bitcast (void (i32*, i32)* @aiAccum to i8*), align 4
@.rs.reduce_fn.dpAccum = global i8* bitcast (void (float*, float, float)* @dpAccum to i8*), align 4
@.rs.reduce_fn.dpSum = global i8* bitcast (void (float*, float*)* @dpSum to i8*), align 4
@.rs.reduce_fn.fMMInit = global i8* bitcast (void (%struct.MinAndMax*)* @fMMInit to i8*), align 4
@.rs.reduce_fn.fMMAccumulator = global i8* bitcast (void (%struct.MinAndMax*, float, i32)* @fMMAccumulator to i8*), align 4
@.rs.reduce_fn.fMMCombiner = global i8* bitcast (void (%struct.MinAndMax*, %struct.MinAndMax*)* @fMMCombiner to i8*), align 4
@.rs.reduce_fn.fMMOutConverter = global i8* bitcast (void (<2 x i32>*, %struct.MinAndMax*)* @fMMOutConverter to i8*), align 4
@.rs.reduce_fn.fzInit = global i8* bitcast (void (i32*)* @fzInit to i8*), align 4
@.rs.reduce_fn.fzAccum = global i8* bitcast (void (i32*, i32, i32)* @fzAccum to i8*), align 4
@.rs.reduce_fn.fzCombine = global i8* bitcast (void (i32*, i32*)* @fzCombine to i8*), align 4
@.rs.reduce_fn.fz2Init = global i8* bitcast (void (<2 x i32>*)* @fz2Init to i8*), align 4
@.rs.reduce_fn.fz2Accum = global i8* bitcast (void (<2 x i32>*, i32, i32, i32)* @fz2Accum to i8*), align 4
@.rs.reduce_fn.fz2Combine = global i8* bitcast (void (<2 x i32>*, <2 x i32>*)* @fz2Combine to i8*), align 4
@.rs.reduce_fn.fz3Init = global i8* bitcast (void (<3 x i32>*)* @fz3Init to i8*), align 4
@.rs.reduce_fn.fz3Accum = global i8* bitcast (void (<3 x i32>*, i32, i32, i32, i32)* @fz3Accum to i8*), align 4
@.rs.reduce_fn.fz3Combine = global i8* bitcast (void (<3 x i32>*, <3 x i32>*)* @fz3Combine to i8*), align 4
@.rs.reduce_fn.hsgAccum = global i8* bitcast (void ([256 x i32]*, i8)* @hsgAccum to i8*), align 4
@.rs.reduce_fn.hsgCombine = global i8* bitcast (void ([256 x i32]*, [256 x i32]*)* @hsgCombine to i8*), align 4
@.rs.reduce_fn.modeOutConvert = global i8* bitcast (void (<2 x i32>*, [256 x i32]*)* @modeOutConvert to i8*), align 4
@negInf = common global float 0.000000e+00, align 4
@posInf = common global float 0.000000e+00, align 4
; Function Attrs: nounwind
define internal void @aiAccum(i32* nocapture %accum, i32 %val) #0 {
%1 = load i32, i32* %accum, align 4, !tbaa !22
%2 = add nsw i32 %1, %val
store i32 %2, i32* %accum, align 4, !tbaa !22
ret void
}
; Function Attrs: nounwind
define internal void @dpAccum(float* nocapture %accum, float %in1, float %in2) #0 {
%1 = fmul float %in1, %in2
%2 = load float, float* %accum, align 4, !tbaa !26
%3 = fadd float %1, %2
store float %3, float* %accum, align 4, !tbaa !26
ret void
}
; Function Attrs: nounwind
define internal void @dpSum(float* nocapture %accum, float* nocapture %val) #0 {
%1 = load float, float* %val, align 4, !tbaa !26
%2 = load float, float* %accum, align 4, !tbaa !26
%3 = fadd float %1, %2
store float %3, float* %accum, align 4, !tbaa !26
ret void
}
; Function Attrs: nounwind
define internal void @fMMInit(%struct.MinAndMax* nocapture %accum) #0 {
%1 = load i32, i32* bitcast (float* @posInf to i32*), align 4, !tbaa !26
%2 = bitcast %struct.MinAndMax* %accum to i32*
store i32 %1, i32* %2, align 4, !tbaa !26
%3 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 0, i32 1
store i32 -1, i32* %3, align 4, !tbaa !22
%4 = load i32, i32* bitcast (float* @negInf to i32*), align 4, !tbaa !26
%5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1
%6 = bitcast %struct.IndexedVal* %5 to i32*
store i32 %4, i32* %6, align 4, !tbaa !26
%7 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1, i32 1
store i32 -1, i32* %7, align 4, !tbaa !22
ret void
}
; Function Attrs: nounwind
define internal void @fMMAccumulator(%struct.MinAndMax* nocapture %accum, float %in, i32 %x) #0 {
%1 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 0, i32 0
%2 = load float, float* %1, align 4, !tbaa !26
%3 = fcmp ogt float %2, %in
br i1 %3, label %4, label %6
; <label>:4 ; preds = %0
store float %in, float* %1, align 4
%5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 0, i32 1
store i32 %x, i32* %5, align 4
br label %6
; <label>:6 ; preds = %4, %0
%7 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1, i32 0
%8 = load float, float* %7, align 4, !tbaa !26
%9 = fcmp olt float %8, %in
br i1 %9, label %10, label %12
; <label>:10 ; preds = %6
store float %in, float* %7, align 4
%11 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %accum, i32 0, i32 1, i32 1
store i32 %x, i32* %11, align 4
br label %12
; <label>:12 ; preds = %10, %6
ret void
}
; Function Attrs: nounwind
define internal void @fMMCombiner(%struct.MinAndMax* nocapture %accum, %struct.MinAndMax* nocapture %val) #0 {
%1 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 0, i32 0
%2 = load float, float* %1, align 4, !tbaa !26
%3 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 0, i32 1
%4 = load i32, i32* %3, align 4, !tbaa !22
tail call void @fMMAccumulator(%struct.MinAndMax* %accum, float %2, i32 %4)
%5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 1, i32 0
%6 = load float, float* %5, align 4, !tbaa !26
%7 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 1, i32 1
%8 = load i32, i32* %7, align 4, !tbaa !22
tail call void @fMMAccumulator(%struct.MinAndMax* %accum, float %6, i32 %8)
ret void
}
; Function Attrs: nounwind
define internal void @fMMOutConverter(<2 x i32>* nocapture %result, %struct.MinAndMax* nocapture %val) #0 {
%1 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 0, i32 1
%2 = load i32, i32* %1, align 4, !tbaa !22
%3 = load <2 x i32>, <2 x i32>* %result, align 8
%4 = insertelement <2 x i32> %3, i32 %2, i32 0
store <2 x i32> %4, <2 x i32>* %result, align 8
%5 = getelementptr inbounds %struct.MinAndMax, %struct.MinAndMax* %val, i32 0, i32 1, i32 1
%6 = load i32, i32* %5, align 4, !tbaa !22
%7 = insertelement <2 x i32> %4, i32 %6, i32 1
store <2 x i32> %7, <2 x i32>* %result, align 8
ret void
}
; Function Attrs: nounwind
define internal void @fzInit(i32* nocapture %accumIdx) #0 {
store i32 -1, i32* %accumIdx, align 4, !tbaa !22
ret void
}
; Function Attrs: nounwind
define internal void @fzAccum(i32* nocapture %accumIdx, i32 %inVal, i32 %x) #0 {
%1 = icmp eq i32 %inVal, 0
br i1 %1, label %2, label %3
; <label>:2 ; preds = %0
store i32 %x, i32* %accumIdx, align 4, !tbaa !22
br label %3
; <label>:3 ; preds = %2, %0
ret void
}
; Function Attrs: nounwind
define internal void @fzCombine(i32* nocapture %accumIdx, i32* nocapture %accumIdx2) #0 {
%1 = load i32, i32* %accumIdx2, align 4, !tbaa !22
%2 = icmp sgt i32 %1, -1
br i1 %2, label %3, label %4
; <label>:3 ; preds = %0
store i32 %1, i32* %accumIdx, align 4, !tbaa !22
br label %4
; <label>:4 ; preds = %3, %0
ret void
}
; Function Attrs: nounwind
define internal void @fz2Init(<2 x i32>* nocapture %accum) #0 {
store <2 x i32> <i32 -1, i32 -1>, <2 x i32>* %accum, align 8
ret void
}
; Function Attrs: nounwind
define internal void @fz2Accum(<2 x i32>* nocapture %accum, i32 %inVal, i32 %x, i32 %y) #0 {
%1 = icmp eq i32 %inVal, 0
br i1 %1, label %2, label %5
; <label>:2 ; preds = %0
%3 = insertelement <2 x i32> undef, i32 %x, i32 0
%4 = insertelement <2 x i32> %3, i32 %y, i32 1
store <2 x i32> %4, <2 x i32>* %accum, align 8
br label %5
; <label>:5 ; preds = %2, %0
ret void
}
; Function Attrs: nounwind
define internal void @fz2Combine(<2 x i32>* nocapture %accum, <2 x i32>* nocapture %accum2) #0 {
%1 = load <2 x i32>, <2 x i32>* %accum2, align 8
%2 = extractelement <2 x i32> %1, i32 0
%3 = icmp sgt i32 %2, -1
br i1 %3, label %4, label %5
; <label>:4 ; preds = %0
store <2 x i32> %1, <2 x i32>* %accum, align 8, !tbaa !28
br label %5
; <label>:5 ; preds = %4, %0
ret void
}
; Function Attrs: nounwind
define internal void @fz3Init(<3 x i32>* nocapture %accum) #0 {
store <3 x i32> <i32 -1, i32 -1, i32 -1>, <3 x i32>* %accum, align 16
ret void
}
; Function Attrs: nounwind
define internal void @fz3Accum(<3 x i32>* nocapture %accum, i32 %inVal, i32 %x, i32 %y, i32 %z) #0 {
%1 = icmp eq i32 %inVal, 0
br i1 %1, label %2, label %6
; <label>:2 ; preds = %0
%3 = insertelement <3 x i32> undef, i32 %x, i32 0
%4 = insertelement <3 x i32> %3, i32 %y, i32 1
%5 = insertelement <3 x i32> %4, i32 %z, i32 2
store <3 x i32> %5, <3 x i32>* %accum, align 16
br label %6
; <label>:6 ; preds = %2, %0
ret void
}
; Function Attrs: nounwind
define internal void @fz3Combine(<3 x i32>* nocapture %accum, <3 x i32>* nocapture %accum2) #0 {
%1 = load <3 x i32>, <3 x i32>* %accum, align 16
%2 = extractelement <3 x i32> %1, i32 0
%3 = icmp sgt i32 %2, -1
br i1 %3, label %4, label %8
; <label>:4 ; preds = %0
%5 = bitcast <3 x i32>* %accum2 to <4 x i32>*
%6 = load <4 x i32>, <4 x i32>* %5, align 8
%7 = bitcast <3 x i32>* %accum to <4 x i32>*
store <4 x i32> %6, <4 x i32>* %7, align 16, !tbaa !28
br label %8
; <label>:8 ; preds = %4, %0
ret void
}
; Function Attrs: nounwind
define internal void @hsgAccum([256 x i32]* nocapture %h, i8 zeroext %in) #0 {
%1 = zext i8 %in to i32
%2 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %1
%3 = load i32, i32* %2, align 4, !tbaa !22
%4 = add i32 %3, 1
store i32 %4, i32* %2, align 4, !tbaa !22
ret void
}
; Function Attrs: nounwind
define internal void @hsgCombine([256 x i32]* nocapture %accum, [256 x i32]* nocapture %addend) #0 {
br label %2
; <label>:1 ; preds = %2
ret void
; <label>:2 ; preds = %2, %0
%i.01 = phi i32 [ 0, %0 ], [ %8, %2 ]
%3 = getelementptr inbounds [256 x i32], [256 x i32]* %addend, i32 0, i32 %i.01
%4 = load i32, i32* %3, align 4, !tbaa !22
%5 = getelementptr inbounds [256 x i32], [256 x i32]* %accum, i32 0, i32 %i.01
%6 = load i32, i32* %5, align 4, !tbaa !22
%7 = add i32 %6, %4
store i32 %7, i32* %5, align 4, !tbaa !22
%8 = add nuw nsw i32 %i.01, 1
%exitcond = icmp eq i32 %8, 256
br i1 %exitcond, label %1, label %2
}
; Function Attrs: nounwind
define internal void @modeOutConvert(<2 x i32>* nocapture %result, [256 x i32]* nocapture %h) #0 {
br label %7
; <label>:1 ; preds = %7
%2 = load <2 x i32>, <2 x i32>* %result, align 8
%3 = insertelement <2 x i32> %2, i32 %i.0.mode.0, i32 0
store <2 x i32> %3, <2 x i32>* %result, align 8
%4 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %i.0.mode.0
%5 = load i32, i32* %4, align 4, !tbaa !22
%6 = insertelement <2 x i32> %3, i32 %5, i32 1
store <2 x i32> %6, <2 x i32>* %result, align 8
ret void
; <label>:7 ; preds = %7, %0
%i.02 = phi i32 [ 1, %0 ], [ %13, %7 ]
%mode.01 = phi i32 [ 0, %0 ], [ %i.0.mode.0, %7 ]
%8 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %i.02
%9 = load i32, i32* %8, align 4, !tbaa !22
%10 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i32 0, i32 %mode.01
%11 = load i32, i32* %10, align 4, !tbaa !22
%12 = icmp ugt i32 %9, %11
%i.0.mode.0 = select i1 %12, i32 %i.02, i32 %mode.01
%13 = add nuw nsw i32 %i.02, 1
%exitcond = icmp eq i32 %13, 256
br i1 %exitcond, label %1, label %7
}
attributes #0 = { nounwind }
!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}
!\23pragma = !{!3, !4}
!\23rs_export_var = !{!5, !6}
!\23rs_object_slots = !{}
!\23rs_export_reduce = !{!7, !9, !11, !13, !15, !17, !19, !21}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"min_enum_size", i32 4}
!2 = !{!"clang version 3.6 "}
!3 = !{!"version", !"1"}
!4 = !{!"java_package_name", !"com.android.rs.test"}
!5 = !{!"negInf", !"1"}
!6 = !{!"posInf", !"1"}
!7 = !{!"addint", !"4", !8}
!8 = !{!"aiAccum", !"1"}
!9 = !{!"dp", !"4", !10, null, !"dpSum"}
!10 = !{!"dpAccum", !"1"}
!11 = !{!"findMinAndMax", !"16", !12, !"fMMInit", !"fMMCombiner", !"fMMOutConverter"}
!12 = !{!"fMMAccumulator", !"9"}
!13 = !{!"fz", !"4", !14, !"fzInit", !"fzCombine"}
!14 = !{!"fzAccum", !"9"}
!15 = !{!"fz2", !"8", !16, !"fz2Init", !"fz2Combine"}
!16 = !{!"fz2Accum", !"25"}
!17 = !{!"fz3", !"16", !18, !"fz3Init", !"fz3Combine"}
!18 = !{!"fz3Accum", !"89"}
!19 = !{!"histogram", !"1024", !20, null, !"hsgCombine"}
!20 = !{!"hsgAccum", !"1"}
!21 = !{!"mode", !"1024", !20, null, !"hsgCombine", !"modeOutConvert"}
!22 = !{!23, !23, i64 0}
!23 = !{!"int", !24, i64 0}
!24 = !{!"omnipotent char", !25, i64 0}
!25 = !{!"Simple C/C++ TBAA"}
!26 = !{!27, !27, i64 0}
!27 = !{!"float", !24, i64 0}
!28 = !{!24, !24, i64 0}

View file

@ -0,0 +1,333 @@
; Check that the #rs_export_reduce node is recognized.
; RUN: llvm-rs-as %s -o %t
; RUN: bcinfo %t | FileCheck %s
; CHECK: exportReduceCount: 8
; CHECK: exportReduceList[0]: addint - 0x00000001 - 1 - 4
; CHECK: accumulator(aiAccum)
; CHECK: exportReduceList[1]: mpyint - 0x00000001 - 1 - 4
; CHECK: initializer(mpyInit)
; CHECK: accumulator(mpyAccum)
; CHECK: exportReduceList[2]: dp - 0x00000001 - 2 - 4
; CHECK: accumulator(dpAccum)
; CHECK: combiner(dpSum)
; CHECK: exportReduceList[3]: findMinAndMax - 0x00000009 - 1 - 16
; CHECK: initializer(fMMInit)
; CHECK: accumulator(fMMAccumulator)
; CHECK: combiner(fMMCombiner)
; CHECK: outconverter(fMMOutConverter)
; CHECK: exportReduceList[4]: fz - 0x00000009 - 1 - 4
; CHECK: initializer(fzInit)
; CHECK: accumulator(fzAccum)
; CHECK: combiner(fzCombine)
; CHECK: halter(fzFound)
; CHECK: exportReduceList[5]: fz2 - 0x00000019 - 1 - 8
; CHECK: initializer(fz2Init)
; CHECK: accumulator(fz2Accum)
; CHECK: combiner(fz2Combine)
; CHECK: halter(fz2Found)
; CHECK: exportReduceList[6]: histogram - 0x00000001 - 1 - 1024
; CHECK: accumulator(hsgAccum)
; CHECK: combiner(hsgCombine)
; CHECK: exportReduceList[7]: mode - 0x00000001 - 1 - 1024
; CHECK: accumulator(hsgAccum)
; CHECK: combiner(hsgCombine)
; CHECK: outconverter(modeOutConvert)
; ModuleID = 'reduce_general_examples.bc'
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-none-linux-gnueabi"
%struct.MinAndMax.0 = type { %struct.IndexedVal.1, %struct.IndexedVal.1 }
%struct.IndexedVal.1 = type { float, i32 }
@fMMInit.r = internal unnamed_addr constant %struct.MinAndMax.0 { %struct.IndexedVal.1 { float 0.000000e+00, i32 -1 }, %struct.IndexedVal.1 { float -0.000000e+00, i32 -1 } }, align 4
@llvm.used = appending global [20 x i8*] [i8* bitcast (void (<2 x i32>*)* @fz2Init to i8*), i8* bitcast (void ([256 x i32]*, [256 x i32]*)* @hsgCombine to i8*), i8* bitcast (i1 (<2 x i32>*)* @fz2Found to i8*), i8* bitcast (void (i32*, i32)* @mpyAccum to i8*), i8* bitcast (void (%struct.MinAndMax.0*)* @fMMInit to i8*), i8* bitcast (void (float*, float, float)* @dpAccum to i8*), i8* bitcast (void (<2 x i32>*, [256 x i32]*)* @modeOutConvert to i8*), i8* bitcast (void ([256 x i32]*, i8)* @hsgAccum to i8*), i8* bitcast (void (i32*)* @mpyInit to i8*), i8* bitcast (void (%struct.MinAndMax.0*, float, i32)* @fMMAccumulator to i8*), i8* bitcast (void (float*, float*)* @dpSum to i8*), i8* bitcast (void (%struct.MinAndMax.0*, %struct.MinAndMax.0*)* @fMMCombiner to i8*), i8* bitcast (void (i32*, i32*)* @fzCombine to i8*), i8* bitcast (void (i32*, i32)* @aiAccum to i8*), i8* bitcast (void (i32*)* @fzInit to i8*), i8* bitcast (void (i32*, i32, i32)* @fzAccum to i8*), i8* bitcast (i1 (i32*)* @fzFound to i8*), i8* bitcast (void (<2 x i32>*, i32, i32, i32)* @fz2Accum to i8*), i8* bitcast (void (<2 x i32>*, %struct.MinAndMax.0*)* @fMMOutConverter to i8*), i8* bitcast (void (<2 x i32>*, <2 x i32>*)* @fz2Combine to i8*)], section "llvm.metadata"
; Function Attrs: nounwind
define internal void @aiAccum(i32* nocapture %accum, i32 %val) #0 {
%1 = load i32, i32* %accum, align 4, !tbaa !18
%2 = add nsw i32 %1, %val
store i32 %2, i32* %accum, align 4, !tbaa !18
ret void
}
; Function Attrs: nounwind
define internal void @mpyInit(i32* nocapture %accum) #0 {
store i32 1, i32* %accum, align 4, !tbaa !18
ret void
}
; Function Attrs: nounwind
define internal void @mpyAccum(i32* nocapture %accum, i32 %val) #0 {
%1 = load i32, i32* %accum, align 4, !tbaa !18
%2 = mul nsw i32 %1, %val
store i32 %2, i32* %accum, align 4, !tbaa !18
ret void
}
; Function Attrs: nounwind
define internal void @dpAccum(float* nocapture %accum, float %in1, float %in2) #0 {
%1 = fmul float %in1, %in2
%2 = load float, float* %accum, align 4, !tbaa !22
%3 = fadd float %1, %2
store float %3, float* %accum, align 4, !tbaa !22
ret void
}
; Function Attrs: nounwind
define internal void @dpSum(float* nocapture %accum, float* nocapture %val) #0 {
%1 = load float, float* %val, align 4, !tbaa !22
%2 = load float, float* %accum, align 4, !tbaa !22
%3 = fadd float %1, %2
store float %3, float* %accum, align 4, !tbaa !22
ret void
}
; Function Attrs: nounwind
define internal void @fMMInit(%struct.MinAndMax.0* nocapture %accum) #0 {
%1 = bitcast %struct.MinAndMax.0* %accum to i8*
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast (%struct.MinAndMax.0* @fMMInit.r to i8*), i64 16, i32 4, i1 false), !tbaa.struct !24
ret void
}
; Function Attrs: nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
; Function Attrs: nounwind
define internal void @fMMAccumulator(%struct.MinAndMax.0* nocapture %accum, float %in, i32 %x) #0 {
%1 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 0, i32 0
%2 = load float, float* %1, align 4, !tbaa !22
%3 = fcmp ogt float %2, %in
br i1 %3, label %4, label %6
; <label>:4 ; preds = %0
store float %in, float* %1, align 4
%5 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 0, i32 1
store i32 %x, i32* %5, align 4
br label %6
; <label>:6 ; preds = %4, %0
%7 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 1, i32 0
%8 = load float, float* %7, align 4, !tbaa !22
%9 = fcmp olt float %8, %in
br i1 %9, label %10, label %12
; <label>:10 ; preds = %6
store float %in, float* %7, align 4
%11 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %accum, i64 0, i32 1, i32 1
store i32 %x, i32* %11, align 4
br label %12
; <label>:12 ; preds = %10, %6
ret void
}
; Function Attrs: nounwind
define internal void @fMMCombiner(%struct.MinAndMax.0* nocapture %accum, %struct.MinAndMax.0* nocapture %val) #0 {
%1 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 0, i32 0
%2 = load float, float* %1, align 4, !tbaa !22
%3 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 0, i32 1
%4 = load i32, i32* %3, align 4, !tbaa !18
tail call void @fMMAccumulator(%struct.MinAndMax.0* %accum, float %2, i32 %4)
%5 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 1, i32 0
%6 = load float, float* %5, align 4, !tbaa !22
%7 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 1, i32 1
%8 = load i32, i32* %7, align 4, !tbaa !18
tail call void @fMMAccumulator(%struct.MinAndMax.0* %accum, float %6, i32 %8)
ret void
}
; Function Attrs: nounwind
define internal void @fMMOutConverter(<2 x i32>* nocapture %result, %struct.MinAndMax.0* nocapture %val) #0 {
%1 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 0, i32 1
%2 = load i32, i32* %1, align 4, !tbaa !18
%3 = load <2 x i32>, <2 x i32>* %result, align 8
%4 = insertelement <2 x i32> %3, i32 %2, i64 0
store <2 x i32> %4, <2 x i32>* %result, align 8
%5 = getelementptr inbounds %struct.MinAndMax.0, %struct.MinAndMax.0* %val, i64 0, i32 1, i32 1
%6 = load i32, i32* %5, align 4, !tbaa !18
%7 = insertelement <2 x i32> %4, i32 %6, i64 1
store <2 x i32> %7, <2 x i32>* %result, align 8
ret void
}
; Function Attrs: nounwind
define internal void @fzInit(i32* nocapture %accumIdx) #0 {
store i32 -1, i32* %accumIdx, align 4, !tbaa !18
ret void
}
; Function Attrs: nounwind
define internal void @fzAccum(i32* nocapture %accumIdx, i32 %inVal, i32 %x) #0 {
%1 = icmp eq i32 %inVal, 0
br i1 %1, label %2, label %3
; <label>:2 ; preds = %0
store i32 %x, i32* %accumIdx, align 4, !tbaa !18
br label %3
; <label>:3 ; preds = %2, %0
ret void
}
; Function Attrs: nounwind
define internal void @fzCombine(i32* nocapture %accumIdx, i32* nocapture %accumIdx2) #0 {
%1 = load i32, i32* %accumIdx2, align 4, !tbaa !18
%2 = icmp sgt i32 %1, -1
br i1 %2, label %3, label %4
; <label>:3 ; preds = %0
store i32 %1, i32* %accumIdx, align 4, !tbaa !18
br label %4
; <label>:4 ; preds = %3, %0
ret void
}
; Function Attrs: nounwind readonly
define internal i1 @fzFound(i32* nocapture %accumIdx) #1 {
%1 = load i32, i32* %accumIdx, align 4, !tbaa !18
%2 = icmp sgt i32 %1, -1
ret i1 %2
}
; Function Attrs: nounwind
define internal void @fz2Init(<2 x i32>* nocapture %accum) #0 {
store <2 x i32> <i32 -1, i32 -1>, <2 x i32>* %accum, align 8
ret void
}
; Function Attrs: nounwind
define internal void @fz2Accum(<2 x i32>* nocapture %accum, i32 %inVal, i32 %x, i32 %y) #0 {
%1 = icmp eq i32 %inVal, 0
br i1 %1, label %2, label %5
; <label>:2 ; preds = %0
%3 = insertelement <2 x i32> undef, i32 %x, i64 0
%4 = insertelement <2 x i32> %3, i32 %y, i64 1
store <2 x i32> %4, <2 x i32>* %accum, align 8
br label %5
; <label>:5 ; preds = %2, %0
ret void
}
; Function Attrs: nounwind
define internal void @fz2Combine(<2 x i32>* nocapture %accum, <2 x i32>* nocapture %accum2) #0 {
%1 = load <2 x i32>, <2 x i32>* %accum2, align 8
%2 = extractelement <2 x i32> %1, i64 0
%3 = icmp sgt i32 %2, -1
br i1 %3, label %4, label %5
; <label>:4 ; preds = %0
store <2 x i32> %1, <2 x i32>* %accum, align 8, !tbaa !25
br label %5
; <label>:5 ; preds = %4, %0
ret void
}
; Function Attrs: nounwind readonly
define internal i1 @fz2Found(<2 x i32>* nocapture %accum) #1 {
%1 = load <2 x i32>, <2 x i32>* %accum, align 8
%2 = extractelement <2 x i32> %1, i64 0
%3 = icmp sgt i32 %2, -1
ret i1 %3
}
; Function Attrs: nounwind
define internal void @hsgAccum([256 x i32]* nocapture %h, i8 %in) #0 {
%1 = zext i8 %in to i64
%2 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %1
%3 = load i32, i32* %2, align 4, !tbaa !18
%4 = add i32 %3, 1
store i32 %4, i32* %2, align 4, !tbaa !18
ret void
}
; Function Attrs: nounwind
define internal void @hsgCombine([256 x i32]* nocapture %accum, [256 x i32]* nocapture %addend) #0 {
br label %2
; <label>:1 ; preds = %2
ret void
; <label>:2 ; preds = %2, %0
%indvars.iv = phi i64 [ 0, %0 ], [ %indvars.iv.next, %2 ]
%3 = getelementptr inbounds [256 x i32], [256 x i32]* %addend, i64 0, i64 %indvars.iv
%4 = load i32, i32* %3, align 4, !tbaa !18
%5 = getelementptr inbounds [256 x i32], [256 x i32]* %accum, i64 0, i64 %indvars.iv
%6 = load i32, i32* %5, align 4, !tbaa !18
%7 = add i32 %6, %4
store i32 %7, i32* %5, align 4, !tbaa !18
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%exitcond = icmp eq i64 %indvars.iv.next, 256
br i1 %exitcond, label %1, label %2
}
; Function Attrs: nounwind
define internal void @modeOutConvert(<2 x i32>* nocapture %result, [256 x i32]* nocapture %h) #0 {
br label %8
; <label>:1 ; preds = %8
%2 = load <2 x i32>, <2 x i32>* %result, align 8
%3 = insertelement <2 x i32> %2, i32 %i.0.mode.0, i64 0
store <2 x i32> %3, <2 x i32>* %result, align 8
%4 = zext i32 %i.0.mode.0 to i64
%5 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %4
%6 = load i32, i32* %5, align 4, !tbaa !18
%7 = insertelement <2 x i32> %3, i32 %6, i64 1
store <2 x i32> %7, <2 x i32>* %result, align 8
ret void
; <label>:8 ; preds = %8, %0
%indvars.iv = phi i64 [ 1, %0 ], [ %indvars.iv.next, %8 ]
%mode.01 = phi i32 [ 0, %0 ], [ %i.0.mode.0, %8 ]
%9 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %indvars.iv
%10 = load i32, i32* %9, align 4, !tbaa !18
%11 = zext i32 %mode.01 to i64
%12 = getelementptr inbounds [256 x i32], [256 x i32]* %h, i64 0, i64 %11
%13 = load i32, i32* %12, align 4, !tbaa !18
%14 = icmp ugt i32 %10, %13
%15 = trunc i64 %indvars.iv to i32
%i.0.mode.0 = select i1 %14, i32 %15, i32 %mode.01
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
%exitcond = icmp eq i64 %indvars.iv.next, 256
br i1 %exitcond, label %1, label %8
}
attributes #0 = { nounwind }
attributes #1 = { nounwind readonly }
!llvm.ident = !{!0}
!\23pragma = !{!1, !2}
!\23rs_export_reduce = !{!3, !5, !7, !9, !11, !13, !15, !17}
!0 = !{!"clang version 3.6 "}
!1 = !{!"version", !"1"}
!2 = !{!"java_package_name", !"examples"}
!3 = !{!"addint", !"4", !4}
!4 = !{!"aiAccum", !"1"}
!5 = !{!"mpyint", !"4", !6, !"mpyInit"}
!6 = !{!"mpyAccum", !"1"}
!7 = !{!"dp", !"4", !8, null, !"dpSum"}
!8 = !{!"dpAccum", !"1"}
!9 = !{!"findMinAndMax", !"16", !10, !"fMMInit", !"fMMCombiner", !"fMMOutConverter"}
!10 = !{!"fMMAccumulator", !"9"}
!11 = !{!"fz", !"4", !12, !"fzInit", !"fzCombine", null, !"fzFound"}
!12 = !{!"fzAccum", !"9"}
!13 = !{!"fz2", !"8", !14, !"fz2Init", !"fz2Combine", null, !"fz2Found"}
!14 = !{!"fz2Accum", !"25"}
!15 = !{!"histogram", !"1024", !16, null, !"hsgCombine"}
!16 = !{!"hsgAccum", !"1"}
!17 = !{!"mode", !"1024", !16, null, !"hsgCombine", !"modeOutConvert"}
!18 = !{!19, !19, i64 0}
!19 = !{!"int", !20, i64 0}
!20 = !{!"omnipotent char", !21, i64 0}
!21 = !{!"Simple C/C++ TBAA"}
!22 = !{!23, !23, i64 0}
!23 = !{!"float", !20, i64 0}
!24 = !{i64 0, i64 4, !22, i64 4, i64 4, !18, i64 8, i64 4, !22, i64 12, i64 4, !18}
!25 = !{!20, !20, i64 0}

View file

@ -0,0 +1,113 @@
; Check that bcc properly emits the respective slang and bcc llvm versions used
; to generate the source into the `.rs.info` symbol that's placed in the
; `.rodata` section of the ELF output file.
; RUN: sed s/REPLACE_LLVM_VERSION_STRING_HERE/%LLVM_VERSION_STRING/g %s \
; RUN: | llvm-as -o %t.known-version
; synthetic version of slang that will likely not exist in the wild
; RUN: sed s/REPLACE_LLVM_VERSION_STRING_HERE/VERSIONDOESNOTEXIST/g %s \
; RUN: | llvm-as -o %t.unknown-version
; RUN: bcc -o test_slang_version_info-known-version -output_path %T \
; RUN: -bclib libclcore.bc -mtriple armv7-none-linux-gnueabi -O0 \
; RUN: -embedRSInfo %t.known-version 2>%t.stderr.known-version
; RUN: bcc -o test_slang_version_info-unknown-version -output_path %T \
; RUN: -bclib libclcore.bc -mtriple armv7-none-linux-gnueabi -O0 \
; RUN: -embedRSInfo %t.unknown-version 2>%t.stderr.unknown-version
; Assert that bcc warns that there is a mismatch when slang version is the string "DOESNOTEXIST"
; RUN: FileCheck %s -check-prefix=CHECK_BCC_WARNING < %t.stderr.unknown-version
; Assert that bcc does not warn when there is a version match
; RUN: FileCheck %s -check-prefix=CHECK_BCC_NOWARNING < %t.stderr.known-version
; Assert that bcc emits the correct version info into the .rs.info symbol
; RUN: readelf --wide --string-dump=.rodata %T/test_slang_version_info-known-version.o \
; RUN: | FileCheck %s -check-prefix=CHECK_KNOWN_VERSION
; Assert that bcc emits the correct version info into the .rs.info symbol
; RUN: readelf --wide --string-dump=.rodata %T/test_slang_version_info-unknown-version.o \
; RUN: | FileCheck %s -check-prefix=CHECK_UNKNOWN_VERSION
; Finally check whether bcc is happy with a file that doesn't contain the
; version metatadata for compatibility with old versions of bitcode
; RUN: grep -v slang.llvm.version %s | llvm-as -o %t.no-version
; RUN: bcc -o test_slang_version_info-known-version -output_path %T \
; RUN: -bclib libclcore.bc -mtriple armv7-none-linux-gnueabi -O0 \
; RUN: -embedRSInfo %t.no-version 2> %t.stderr.no-version
; CHECK_UNKNOWN_VERSION: {{.*}}versionInfo: 2^Jbcc - {{[0-9]+.[0-9]+.[0-9]+}}^Jslang - VERSIONDOESNOTEXIST
; CHECK_KNOWN_VERSION: {{.*}}versionInfo: 2^Jbcc - {{[0-9]+.[0-9]+.[0-9]+}}^Jslang - {{[0-9]+.[0-9]+.[0-9]+}}
; CHECK_BCC_WARNING: W/bcc {{.*}}VERSIONDOESNOTEXIST, expecting {{[1-9]+.[0-9]+.[0-9]+.*}}The debugging experience may be unreliable
; CHECK_BCC_NOWARNING-NOT: W/bcc {{.*}}The debugging experience may be unreliable
; ModuleID = 'test_slang_version_info.bc'
target datalayout = "e-p:32:32-i64:64-v128:64:128-n32-S64"
target triple = "armv7-none-linux-gnueabi"
; Function Attrs: nounwind
define <4 x i8> @swizzle(<4 x i8> %in) #0 !dbg !4 {
%1 = alloca <4 x i8>, align 4
%result = alloca <4 x i8>, align 4
store <4 x i8> %in, <4 x i8>* %1, align 4
call void @llvm.dbg.declare(metadata <4 x i8>* %1, metadata !27, metadata !28), !dbg !29
call void @llvm.dbg.declare(metadata <4 x i8>* %result, metadata !30, metadata !28), !dbg !31
%2 = load <4 x i8>, <4 x i8>* %1, align 4, !dbg !31
%3 = shufflevector <4 x i8> %2, <4 x i8> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>, !dbg !31
store <4 x i8> %3, <4 x i8>* %result, align 4, !dbg !31
%4 = load <4 x i8>, <4 x i8>* %result, align 4, !dbg !32
ret <4 x i8> %4, !dbg !32
}
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="0" "stackrealign" "target-features"="+long64" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind readnone }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!16, !17, !18}
!llvm.ident = !{!19}
!\23pragma = !{!20, !21}
!\23rs_export_foreach_name = !{!22, !23}
!\23rs_export_foreach = !{!24, !25}
!slang.llvm.version = !{!26}
!0 = distinct !DICompileUnit(language: DW_LANG_GOOGLE_RenderScript, file: !1, producer: "Android clang version 3.8.256229 (based on LLVM 3.8.256229)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2)
!1 = !DIFile(filename: "test_slang_version_info.rs", directory: ".")
!2 = !{}
!3 = !{!4}
!4 = distinct !DISubprogram(name: "swizzle", scope: !5, file: !5, line: 5, type: !6, isLocal: false, isDefinition: true, scopeLine: 6, isOptimized: false, unit: !0, variables: !2)
!5 = !DIFile(filename: "test_slang_version_info.rs", directory: ".")
!6 = !DISubroutineType(types: !7)
!7 = !{!8, !8}
!8 = !DIDerivedType(tag: DW_TAG_typedef, name: "uchar4", file: !9, line: 328, baseType: !10)
!9 = !DIFile(filename: "frameworks/rs/scriptc/rs_value_types.rsh", directory: ".")
!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, flags: DIFlagVector, elements: !14)
!11 = !DIDerivedType(tag: DW_TAG_typedef, name: "uchar", file: !9, line: 206, baseType: !12)
!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint8_t", file: !9, line: 172, baseType: !13)
!13 = !DIBasicType(name: "unsigned char", size: 8, align: 8, encoding: DW_ATE_unsigned_char)
!14 = !{!15}
!15 = !DISubrange(count: 4)
!16 = !{i32 2, !"Debug Info Version", i32 3}
!17 = !{i32 1, !"wchar_size", i32 4}
!18 = !{i32 1, !"min_enum_size", i32 4}
!19 = !{!"Android clang version 3.8.256229 (based on LLVM 3.8.256229)"}
!20 = !{!"version", !"1"}
!21 = !{!"java_package_name", !"com.android.libbcc.test_version_info"}
!22 = !{!"root"}
!23 = !{!"swizzle"}
!24 = !{!"0"}
!25 = !{!"35"}
!26 = !{!"REPLACE_LLVM_VERSION_STRING_HERE"}
!27 = !DILocalVariable(name: "in", arg: 1, scope: !4, file: !5, line: 5, type: !8)
!28 = !DIExpression()
!29 = !DILocation(line: 5, scope: !4)
!30 = !DILocalVariable(name: "result", scope: !4, file: !5, line: 7, type: !8)
!31 = !DILocation(line: 7, scope: !4)
!32 = !DILocation(line: 8, scope: !4)

View file

@ -0,0 +1,6 @@
#!/bin/bash -e
LIT_PATH=$ANDROID_BUILD_TOP/frameworks/compile/libbcc/tests/debuginfo/llvm-lit
LIBBCC_TESTS=$ANDROID_BUILD_TOP/frameworks/compile/libbcc/tests/libbcc
$LIT_PATH $LIBBCC_TESTS $@