/* * Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved. * * 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. * */ #include "gbldefs.h" #include "global.h" #include "ll_builder.h" #include "lldebug.h" /* * LLMD_Builder -- Builder for metadata nodes. */ struct LLMD_Builder_ { LL_Module *module; unsigned nelems; unsigned capacity; LL_MDRef *elems; enum LL_MDClass mdclass; unsigned is_distinct : 1; LL_MDRef init_elems[32]; }; LLMD_Builder llmd_init(LL_Module *module) { LLMD_Builder mdb = (LLMD_Builder)calloc(1, sizeof(struct LLMD_Builder_)); mdb->module = module; /* Start out with init_elems to save a malloc() call. */ mdb->elems = mdb->init_elems; mdb->capacity = sizeof(mdb->init_elems) / sizeof(mdb->init_elems[0]); return mdb; } /* Double the capacity in mdb. */ static void grow(LLMD_Builder mdb) { mdb->capacity *= 2; if (mdb->elems == mdb->init_elems) { /* First time we grow, don't free init_elems. */ mdb->elems = (LL_MDRef *)malloc(mdb->capacity * sizeof(mdb->elems[0])); memcpy(mdb->elems, mdb->init_elems, sizeof(mdb->init_elems)); } else { /* We've grown before. Just realloc. */ mdb->elems = (LL_MDRef *)realloc(mdb->elems, mdb->capacity * sizeof(mdb->elems[0])); } } void llmd_add_md(LLMD_Builder mdb, LL_MDRef mdnode) { if (mdb->nelems >= mdb->capacity) grow(mdb); mdb->elems[mdb->nelems++] = mdnode; } void llmd_add_null(LLMD_Builder mdb) { llmd_add_md(mdb, ll_get_md_null()); } void llmd_add_i1(LLMD_Builder mdb, int value) { llmd_add_md(mdb, ll_get_md_i1(value)); } void llmd_add_i32(LLMD_Builder mdb, int value) { llmd_add_md(mdb, ll_get_md_i32(mdb->module, value)); } void llmd_add_i64(LLMD_Builder mdb, long long value) { llmd_add_md(mdb, ll_get_md_i64(mdb->module, value)); } void llmd_add_i64_lsb_msb(LLMD_Builder mdb, unsigned lsb, unsigned msb) { long long value = msb; value <<= 32; value |= lsb; llmd_add_i64(mdb, value); } void llmd_add_INT64(LLMD_Builder mdb, DBLINT64 value) { /* DBLINT64 is big-endian (msb, lsb). */ llmd_add_i64_lsb_msb(mdb, value[1], value[0]); } void llmd_add_string(LLMD_Builder mdb, const char *value) { llmd_add_md(mdb, value ? ll_get_md_string(mdb->module, value) : LL_MDREF_ctor(0, 0)); } void llmd_add_value(LLMD_Builder mdb, LL_Value *value) { llmd_add_md(mdb, ll_get_md_value(mdb->module, value)); } void llmd_reverse(LLMD_Builder mdb) { unsigned i, j; LL_MDRef *e = mdb->elems; if (mdb->nelems <= 1) return; for (i = 0, j = mdb->nelems - 1; i < j; i++, j--) { LL_MDRef t = e[i]; e[i] = e[j]; e[j] = t; } } unsigned llmd_get_nelems(LLMD_Builder mdb) { return mdb->nelems; } void llmd_set_distinct(LLMD_Builder mdb) { mdb->is_distinct = true; } void llmd_set_class(LLMD_Builder mdb, enum LL_MDClass mdclass) { mdb->mdclass = mdclass; } LL_MDRef ll_finish_variable(LLMD_Builder mdb, LL_MDRef fwd) { LL_MDRef mdref; LLVMModuleRef mod = mdb->module; const unsigned mdnodeTop = mod->mdnodes_count; /* create the LL_MDRef */ if (mdb->is_distinct) mdref = ll_create_distinct_md_node(mod, mdb->mdclass, mdb->elems, mdb->nelems); else mdref = ll_get_md_node(mod, mdb->mdclass, mdb->elems, mdb->nelems); /* and move it as needed */ if (!LL_MDREF_IS_NULL(fwd)) { hash_data_t data; const unsigned slot = LL_MDREF_value(fwd); const unsigned mdrefSlot = LL_MDREF_value(mdref) - 1; LL_MDNode *newNode = mod->mdnodes[mdrefSlot]; ll_set_md_node(mod, slot, newNode); if (mod->mdnodes_count == mdnodeTop + 1) --mod->mdnodes_count; mdref = fwd; data = (hash_data_t)INT2HKEY(slot); hashmap_replace(mod->mdnodes_map, newNode, &data); } if (mdb->elems != mdb->init_elems) free(mdb->elems); free(mdb); return mdref; } LL_MDRef llmd_finish(LLMD_Builder mdb) { LL_MDRef mdref; if (mdb->is_distinct) mdref = ll_create_distinct_md_node(mdb->module, mdb->mdclass, mdb->elems, mdb->nelems); else mdref = ll_get_md_node(mdb->module, mdb->mdclass, mdb->elems, mdb->nelems); if (mdb->elems != mdb->init_elems) free(mdb->elems); free(mdb); return mdref; }