| |
| |
| /** |
| * Functions for managing instruction labels. |
| * Basically, this is used to manage the problem of forward branches where |
| * we have a branch instruciton but don't know the target address yet. |
| */ |
| |
| |
| #include "slang_label.h" |
| #include "slang_mem.h" |
| |
| |
| |
| slang_label * |
| _slang_label_new(const char *name) |
| { |
| slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label)); |
| if (l) { |
| l->Name = _slang_strdup(name); |
| l->Location = -1; |
| } |
| return l; |
| } |
| |
| /** |
| * As above, but suffix the name with a unique number. |
| */ |
| slang_label * |
| _slang_label_new_unique(const char *name) |
| { |
| static int id = 1; |
| slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label)); |
| if (l) { |
| l->Name = (char *) _slang_alloc(_mesa_strlen(name) + 10); |
| if (!l->Name) { |
| _mesa_free(l); |
| return NULL; |
| } |
| _mesa_sprintf(l->Name, "%s_%d", name, id); |
| id++; |
| l->Location = -1; |
| } |
| return l; |
| } |
| |
| void |
| _slang_label_delete(slang_label *l) |
| { |
| if (l->Name) { |
| _slang_free(l->Name); |
| l->Name = NULL; |
| } |
| if (l->References) { |
| _slang_free(l->References); |
| l->References = NULL; |
| } |
| _slang_free(l); |
| } |
| |
| |
| void |
| _slang_label_add_reference(slang_label *l, GLuint inst) |
| { |
| const GLuint oldSize = l->NumReferences * sizeof(GLuint); |
| assert(l->Location < 0); |
| l->References = _slang_realloc(l->References, |
| oldSize, oldSize + sizeof(GLuint)); |
| if (l->References) { |
| l->References[l->NumReferences] = inst; |
| l->NumReferences++; |
| } |
| } |
| |
| |
| GLint |
| _slang_label_get_location(const slang_label *l) |
| { |
| return l->Location; |
| } |
| |
| |
| void |
| _slang_label_set_location(slang_label *l, GLint location, |
| struct gl_program *prog) |
| { |
| GLuint i; |
| |
| assert(l->Location < 0); |
| assert(location >= 0); |
| |
| l->Location = location; |
| |
| /* for the instructions that were waiting to learn the label's location: */ |
| for (i = 0; i < l->NumReferences; i++) { |
| const GLuint j = l->References[i]; |
| prog->Instructions[j].BranchTarget = location; |
| } |
| |
| if (l->References) { |
| _slang_free(l->References); |
| l->References = NULL; |
| } |
| } |