#include "rc_test_helpers.h"
#include "unit_test.h"
+static unsigned test_rc_optimize(
+ struct test_result * result,
+ struct radeon_compiler * c,
+ const char * filename)
+{
+ struct rc_test_file test_file;
+
+ test_begin(result);
+
+ if (!load_program(c, &test_file, filename)) {
+ fprintf(stderr, "Failed to load program\n");
+ return 0;
+ }
+
+ rc_optimize(c, NULL);
+ return 1;
+}
+
static void test_runner_rc_optimize(struct test_result * result)
{
+ unsigned pass = 1;
struct radeon_compiler c;
struct rc_instruction *inst;
struct rc_instruction *inst_list[3];
unsigned inst_count = 0;
float const0[4] = {2.0f, 0.0f, 0.0f, 0.0f};
- unsigned pass = 1;
- test_begin(result);
init_compiler(&c, RC_FRAGMENT_PROGRAM, 1, 0);
rc_constants_add_immediate_vec4(&c.Program.Constants, const0);
- add_instruction(&c, "RCP temp[0].x, const[1].x___;");
- add_instruction(&c, "RCP temp[0].y, const[1]._y__;");
- add_instruction(&c, "MUL temp[1].xy, const[0].xx__, temp[0].xy__;");
- add_instruction(&c, "MOV output[0].xy, temp[1].xy;" );
-
- rc_optimize(&c, NULL);
+ test_rc_optimize(result, &c, "omod_two_writers.test");
for(inst = c.Program.Instructions.Next;
- inst != &c.Program.Instructions;
- inst = inst->Next, inst_count++) {
+ inst != &c.Program.Instructions;
+ inst = inst->Next, inst_count++) {
inst_list[inst_count] = inst;
}
inst_list[2]->U.I.Opcode != RC_OPCODE_MOV) {
pass = 0;
}
+
test_check(result, pass);
}
#include "radeon_program.h"
#include "radeon_regalloc.h"
#include "radeon_swizzle.h"
+#include "util/u_math.h"
#include "rc_test_helpers.h"
int Length;
};
+static int is_whitespace(const char *str)
+{
+ regex_t regex;
+ if (regcomp(®ex, "^[ \n]+$", REG_EXTENDED)) {
+ fprintf(stderr, "Failed to compile whitespace regex\n");
+ return 0;
+ }
+ return regexec(®ex, str, 0, NULL, 0) != REG_NOMATCH;
+}
+
static int match_length(regmatch_t * matches, int index)
{
return matches[index].rm_eo - matches[index].rm_so;
unsigned int src_index,
const char * src_str)
{
- const char * regex_str = "(-*)(\\|*)([[:lower:]]*)\\[([[:digit:]])\\](\\.*[[:lower:]-]*)";
+ const char * regex_str = "(-*)(\\|*)([[:lower:]]*)\\[*([[:digit:]]*)\\]*(\\.*[[:lower:]_]*)";
regmatch_t matches[REGEX_SRC_MATCHES];
struct src_tokens tokens;
struct rc_src_register * src_reg = &inst->U.I.SrcReg[src_index];
fprintf(stderr, "First char of swizzle is not valid.\n");
return 0;
}
- for (i = 0; i < 4; i++, str_index++) {
+ for (i = 0; i < 4 && str_index < tokens.Swizzle.Length;
+ i++, str_index++) {
if (tokens.Swizzle.String[str_index] == '-') {
src_reg->Negate |= (1 << i);
str_index++;
SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_UNUSED);
break;
default:
- fprintf(stderr, "Unknown src register swizzle.\n");
+ fprintf(stderr, "Unknown src register swizzle: %c\n",
+ tokens.Swizzle.String[str_index]);
return 0;
}
}
struct rc_instruction * inst,
const char * dst_str)
{
- const char * regex_str = "([[:lower:]]*)\\[([[:digit:]]*)\\](\\.*[[:lower:]]*)";
+ const char * regex_str = "([[:lower:]]*)\\[*([[:digit:]]*)\\]*(\\.*[[:lower:]]*)";
regmatch_t matches[REGEX_DST_MATCHES];
struct dst_tokens tokens;
unsigned int i;
inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
} else if (!strncmp(tokens.File.String, "output", tokens.File.Length)) {
inst->U.I.DstReg.File = RC_FILE_OUTPUT;
+ } else if (!strncmp(tokens.File.String, "none", tokens.File.Length)) {
+ inst->U.I.DstReg.File = RC_FILE_NONE;
+ return 1;
} else {
fprintf(stderr, "Unknown dst register file type.\n");
return 0;
inst->U.I.DstReg.WriteMask |= RC_MASK_W;
break;
default:
- fprintf(stderr, "Unknown swizzle in writemask.\n");
+ fprintf(stderr, "Unknown swizzle in writemask: %c\n",
+ tokens.WriteMask.String[i]);
return 0;
}
}
}
#define REGEX_INST_MATCHES 7
+#define REGEX_CONST_MATCHES 5
struct inst_tokens {
struct match_info Opcode;
struct rc_instruction * inst,
const char * inst_str)
{
- const char * regex_str = "([[:upper:]]+)(_SAT)* ([^,]*)[, ]*([^,]*)[, ]*([^,]*)[, ]*([^;]*)";
+ const char * regex_str = "[[:digit:]: ]*([[:upper:][:digit:]]+)(_SAT)*[ ]*([^,;]*)[, ]*([^,;]*)[, ]*([^,;]*)[, ]*([^;]*)";
int i;
regmatch_t matches[REGEX_INST_MATCHES];
struct inst_tokens tokens;
src_str[tokens.Srcs[j].Length] = '\0';
init_rc_normal_src(inst, j, src_str);
}
+ if (info->HasTexture) {
+ /* XXX: Will this always be XYZW ? */
+ inst->U.I.TexSwizzle = RC_SWIZZLE_XYZW;
+ }
break;
}
return 1;
}
+#define INDEX_TOKEN_LEN 4
+#define FLOAT_TOKEN_LEN 50
+int parse_constant(unsigned *index, float *data, const char *const_str)
+{
+ int matched = sscanf(const_str, "const[%d] {%f, %f, %f, %f}", index,
+ &data[0], &data[1], &data[2], &data[3]);
+ return matched == 5;
+}
+
int init_rc_normal_instruction(
struct rc_instruction * inst,
const char * inst_str)
}
+int add_constant(struct radeon_compiler *c, const char *const_str)
+{
+ float data[4];
+ unsigned index;
+ struct rc_constant_list *constants;
+ struct rc_constant constant;
+
+ if (!parse_constant(&index, data, const_str)) {
+ return 0;
+ }
+
+ constants = &c->Program.Constants;
+ if (constants->_Reserved < index) {
+ struct rc_constant * newlist;
+
+ constants->_Reserved = index + 100;
+
+ newlist = malloc(sizeof(struct rc_constant) * constants->_Reserved);
+ if (constants->Constants) {
+ memcpy(newlist, constants->Constants,
+ sizeof(struct rc_constant) *
+ constants->_Reserved);
+ free(constants->Constants);
+ }
+
+ constants->Constants = newlist;
+ }
+
+ memset(&constant, 0, sizeof(constant));
+ constant.Type = RC_CONSTANT_IMMEDIATE;
+ constant.Size = 4;
+ memcpy(constant.u.Immediate, data, sizeof(float) * 4);
+ constants->Constants[index] = constant;
+ constants->Count = MAX2(constants->Count, index + 1);
+
+ return 1;
+}
+
void init_compiler(
struct radeon_compiler *c,
enum rc_program_type program_type,
unsigned is_r400)
{
struct rc_regalloc_state *rs = malloc(sizeof(struct rc_regalloc_state));
+ rc_init_regalloc_state(rs);
rc_init(c, rs);
c->is_r500 = is_r500;
c->SwizzleCaps = &r300_vertprog_swizzle_caps;
}
}
+
+#define MAX_LINE_LENGTH 100
+#define MAX_PATH_LENGTH 100
+
+unsigned load_program(
+ struct radeon_compiler *c,
+ struct rc_test_file *test,
+ const char *filename)
+{
+ char line[MAX_LINE_LENGTH];
+ char path[MAX_PATH_LENGTH];
+ FILE *file;
+ unsigned *count;
+ char **string_store;
+ unsigned i = 0;
+
+ snprintf(path, MAX_PATH_LENGTH, "compiler/tests/%s", filename);
+ file = fopen(path, "r");
+ if (!file) {
+ return 0;
+ }
+ memset(test, 0, sizeof(struct rc_test_file));
+
+ count = &test->num_input_lines;
+
+ while (fgets(line, MAX_LINE_LENGTH, file)){
+ if (line[MAX_LINE_LENGTH - 2] == '\n') {
+ fprintf(stderr, "Error line cannot be longer than 100 "
+ "characters:\n%s\n", line);
+ return 0;
+ }
+
+ // Comment
+ if (line[0] == '#' || is_whitespace(line)) {
+ continue;
+ }
+
+ if (line[0] == '=') {
+ count = &test->num_expected_lines;
+ continue;
+ }
+
+ (*count)++;
+ }
+
+ test->input = malloc(sizeof(char *) * test->num_input_lines);
+ test->expected = malloc(sizeof(char *) * test->num_expected_lines);
+
+ rewind(file);
+ string_store = test->input;
+
+ while(fgets(line, MAX_LINE_LENGTH, file)) {
+ // Comment
+ char * dst;
+ if (line[0] == '#' || is_whitespace(line)) {
+ continue;
+ }
+
+ if (line[0] == '=') {
+ i = 0;
+ string_store = test->expected;
+ continue;
+ }
+
+ dst = string_store[i++] = malloc((strlen(line) + 1) *
+ sizeof (char));
+ strcpy(dst, line);
+ }
+
+ for (i = 0; i < test->num_input_lines; i++) {
+ if (test->input[i][0] == 'c') {
+ add_constant(c, test->input[i]);
+ continue;
+ }
+ // XXX: Parse immediates from the file.
+ add_instruction(c, test->input[i]);
+ }
+ return 1;
+}