| // RUN: llvm-tblgen %s | FileCheck %s | |
| // RUN: not llvm-tblgen -DERROR_NONLIST %s 2>&1 | FileCheck --check-prefix=ERROR_NONLIST %s | |
| // RUN: not llvm-tblgen -DERROR_KEYTYPE %s 2>&1 | FileCheck --check-prefix=ERROR_KEYTYPE %s | |
| // Sort an already-sorted list — should be a no-op. | |
| // CHECK-LABEL: def idempotent | |
| // CHECK: already = ["a", "b", "c"]; | |
| def idempotent { | |
| list<string> already = !sort(item, ["a", "b", "c"], item); | |
| } | |
| // Sort records by a string field or an int field. The sort is stable, so order | |
| // is preserved on elements with equal key. | |
| // CHECK-LABEL: def key_expr | |
| // CHECK: by_name = [thing_a20, thing_a10, thing_b20, thing_c30, thing_d10]; | |
| // CHECK: by_value = [thing_a10, thing_d10, thing_a20, thing_b20, thing_c30]; | |
| class Thing<string N, int V> { | |
| string Name = N; | |
| int Value = V; | |
| } | |
| def thing_a10 : Thing<"alpha", 10>; | |
| def thing_a20 : Thing<"alpha", 20>; | |
| def thing_b20 : Thing<"beta", 20>; | |
| def thing_c30 : Thing<"charlie", 30>; | |
| def thing_d10 : Thing<"delta", 10>; | |
| defvar Things = [thing_c30, thing_a20, thing_a10, thing_b20, thing_d10]; | |
| def key_expr { | |
| list<Thing> by_name = !sort(t, Things, t.Name); | |
| list<Thing> by_value = !sort(t, Things, t.Value); | |
| } | |
| // Sort a single-element list. | |
| // CHECK-LABEL: def single | |
| // CHECK: one = ["only"]; | |
| def single { | |
| list<string> one = !sort(item, ["only"], item); | |
| } | |
| // CHECK-LABEL: def sorted | |
| // CHECK: sorted_strings = ["axolotl", "barracuda", "cephalopod", "dragonfly"]; | |
| // CHECK: sorted_ints = [1, 2, 3, 5, 8]; | |
| // CHECK: sorted_empty_strings = []; | |
| // CHECK: sorted_empty_ints = []; | |
| defvar EmptyStrings = []<string>; | |
| defvar Creatures = ["cephalopod", "axolotl", "dragonfly", "barracuda"]; | |
| defvar EmptyInts = []<int>; | |
| defvar Nums = [5, 2, 8, 1, 3]; | |
| def sorted { | |
| list<string> sorted_strings = !sort(item, Creatures, item); | |
| list<int> sorted_ints = !sort(n, Nums, n); | |
| list<string> sorted_empty_strings = !sort(item, EmptyStrings, item); | |
| list<int> sorted_empty_ints = !sort(n, EmptyInts, n); | |
| } | |
| #ifdef ERROR_NONLIST | |
| // Dag is not a valid second argument. | |
| def myop; | |
| defvar mydag = (myop); | |
| def err_nonlist { | |
| // ERROR_NONLIST: sort.td:[[@LINE+1]]:38: error: !sort must have a list argument | |
| list<string> bad = !sort(x, mydag, !cast<string>(x)); | |
| } | |
| #endif | |
| #ifdef ERROR_KEYTYPE | |
| // Key that cannot be resolved to int or string leaves the op unfolded. | |
| // ERROR_KEYTYPE: sort.td:[[@LINE+1]]:5: error: Initializer of 'bad' in 'err_keytype' could not be fully resolved | |
| def err_keytype { | |
| list<Thing> bad = !sort(t, Things, t); | |
| } | |
| #endif |