diff --git a/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c b/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c index 018f992640065..58feddeb6bea0 100644 --- a/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c +++ b/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c @@ -18,7 +18,6 @@ // UTC_ARGS: --enable #ifdef __arm__ -/// FIXME: UTC does not find this function, but can find all others. typedef __attribute__((neon_vector_type(8))) __INT8_TYPE__ int8x8_t; int8x8_t test_vaba_s8(int8x8_t a, int8x8_t b, int8x8_t c) { return a + b + c; diff --git a/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c.expected b/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c.expected index 5d514f9d64c02..e17ce61db9c2b 100644 --- a/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c.expected +++ b/clang/test/utils/update_cc_test_checks/Inputs/c-symbol-mangling.c.expected @@ -18,8 +18,22 @@ // UTC_ARGS: --enable #ifdef __arm__ -/// FIXME: UTC does not find this function, but can find all others. typedef __attribute__((neon_vector_type(8))) __INT8_TYPE__ int8x8_t; +// THUMB-DARWIN-LABEL: @test_vaba_s8( +// THUMB-DARWIN-NEXT: entry: +// THUMB-DARWIN-NEXT: [[A_ADDR:%.*]] = alloca <8 x i8>, align 8 +// THUMB-DARWIN-NEXT: [[B_ADDR:%.*]] = alloca <8 x i8>, align 8 +// THUMB-DARWIN-NEXT: [[C_ADDR:%.*]] = alloca <8 x i8>, align 8 +// THUMB-DARWIN-NEXT: store <8 x i8> [[A:%.*]], ptr [[A_ADDR]], align 8 +// THUMB-DARWIN-NEXT: store <8 x i8> [[B:%.*]], ptr [[B_ADDR]], align 8 +// THUMB-DARWIN-NEXT: store <8 x i8> [[C:%.*]], ptr [[C_ADDR]], align 8 +// THUMB-DARWIN-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[A_ADDR]], align 8 +// THUMB-DARWIN-NEXT: [[TMP1:%.*]] = load <8 x i8>, ptr [[B_ADDR]], align 8 +// THUMB-DARWIN-NEXT: [[ADD:%.*]] = add <8 x i8> [[TMP0]], [[TMP1]] +// THUMB-DARWIN-NEXT: [[TMP2:%.*]] = load <8 x i8>, ptr [[C_ADDR]], align 8 +// THUMB-DARWIN-NEXT: [[ADD1:%.*]] = add <8 x i8> [[ADD]], [[TMP2]] +// THUMB-DARWIN-NEXT: ret <8 x i8> [[ADD1]] +// int8x8_t test_vaba_s8(int8x8_t a, int8x8_t b, int8x8_t c) { return a + b + c; } diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index e1cc02e1a608c..1a875c2b523e4 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -557,6 +557,10 @@ def invoke_tool(exe, cmd_args, ir, preprocess_cmd=None, verbose=False): UTC_AVOID = "NOTE: Do not autogenerate" UNUSED_NOTE = "NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:" +DATA_LAYOUT_RE = re.compile( + r"target\s+datalayout\s+=\s+\"(?P.+)\"$", flags=(re.M | re.S) +) + OPT_FUNCTION_RE = re.compile( r"^(\s*;\s*Function\sAttrs:\s(?P[\w\s():,]+?))?\s*define\s+(?P[^@]*)@(?P[\w.$-]+?)\s*" r"(?P\((\)|(.*?[\w.-]+?)\))[^{]*\{)\n(?P.*?)^\}$", @@ -651,6 +655,18 @@ def get_triple_from_march(march): return "x86" +def get_globals_name_prefix(raw_tool_output): + m = DATA_LAYOUT_RE.search(raw_tool_output) + if not m: + return None + data_layout = m.group("layout") + idx = data_layout.find("m:") + if idx < 0: + return None + ch = data_layout[idx + 2] + return "_" if ch == "o" or ch == "x" else None + + def apply_filters(line, filters): has_filter = False for f in filters: diff --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py index 3ffb07ddf6ad8..7a4796eaabb3b 100755 --- a/llvm/utils/update_cc_test_checks.py +++ b/llvm/utils/update_cc_test_checks.py @@ -34,7 +34,7 @@ } -def get_line2func_list(args, clang_args): +def get_line2func_list(args, clang_args, globals_name_prefix): ret = collections.defaultdict(list) # Use clang's JSON AST dump to get the mangled name json_dump_args = [args.clang] + clang_args + ["-fsyntax-only", "-o", "-"] @@ -122,6 +122,14 @@ def parse_clang_ast_json(node, loc, search): if search is None: search = spell mangled = node.get("mangledName", spell) + # Clang's AST dump includes the globals prefix, but when Clang emits + # LLVM IR this is not included and instead added as part of the asm + # output. Strip it from the mangled name of globals when needed + # (see DataLayout::getGlobalPrefix()). + if globals_name_prefix: + storage = node.get("storageClass", None) + if storage != "static" and mangled[0] == globals_name_prefix: + mangled = mangled[1:] ret[int(line) - 1].append((spell, mangled, search)) ast = json.loads(stdout) @@ -249,10 +257,10 @@ def config(): return args, parser -def get_function_body(builder, args, filename, clang_args, extra_commands, prefixes): +def get_function_body( + builder, args, filename, clang_args, extra_commands, prefixes, raw_tool_output +): # TODO Clean up duplication of asm/common build_function_body_dictionary - # Invoke external tool and extract function bodies. - raw_tool_output = common.invoke_tool(args.clang, clang_args, filename) for extra_command in extra_commands: extra_args = shlex.split(extra_command) with tempfile.NamedTemporaryFile() as f: @@ -383,13 +391,23 @@ def main(): common.debug("Extracted clang cmd: clang {}".format(clang_args)) common.debug("Extracted FileCheck prefixes: {}".format(prefixes)) + # Invoke external tool and extract function bodies. + raw_tool_output = common.invoke_tool(ti.args.clang, clang_args, ti.path) get_function_body( - builder, ti.args, ti.path, clang_args, extra_commands, prefixes + builder, + ti.args, + ti.path, + clang_args, + extra_commands, + prefixes, + raw_tool_output, ) # Invoke clang -Xclang -ast-dump=json to get mapping from start lines to # mangled names. Forward all clang args for now. - for k, v in get_line2func_list(ti.args, clang_args).items(): + for k, v in get_line2func_list( + ti.args, clang_args, common.get_globals_name_prefix(raw_tool_output) + ).items(): line2func_list[k].extend(v) func_dict = builder.finish_and_get_func_dict()