Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable escaping from namespaces for inner functions (#208) #210

Merged
merged 6 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dale/CommonDecl/CommonDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ bool addVariable(Unit *unit, const char *name, Type *type,
var->type = type;
var->symbol.append(name);
var->linkage = Linkage::Extern;
bool res = ctx->ns()->addVariable(name, var);
bool res = ctx->addVariable(name, var);
assert(res);
_unused(res);

Expand Down
68 changes: 31 additions & 37 deletions src/dale/Context/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,42 +54,6 @@ Context::~Context() { deleteNamespaces(namespaces); }

Namespace *Context::ns() { return active_ns_nodes.back()->ns; }

bool Context::popUntilNamespace(Namespace *ns) {
assert(ns && "null argument to popUntilNamespace");

for (;;) {
if (active_ns_nodes.size() == 0) {
fprintf(stderr,
"Internal error: no active namespaces left.\n");
abort();
}
if (active_ns_nodes.back()->ns == ns) {
break;
}
active_ns_nodes.pop_back();
}
std::vector<NSNode *> new_used_nodes;
for (;;) {
if (used_ns_nodes.size() == 0) {
fprintf(stderr,
"Internal error: no used namespaces left.\n");
abort();
}
if (used_ns_nodes.back()->ns == ns) {
break;
}
if (used_ns_nodes.back()->ns->name.compare(0, 4, "anon")) {
new_used_nodes.push_back(used_ns_nodes.back());
}
used_ns_nodes.pop_back();
}
std::reverse(new_used_nodes.begin(), new_used_nodes.end());
std::copy(new_used_nodes.begin(), new_used_nodes.end(),
back_inserter(used_ns_nodes));

return true;
}

bool Context::activateNamespace(const char *name) {
assert(active_ns_nodes.size() && "no active namespace nodes");

Expand Down Expand Up @@ -182,6 +146,22 @@ bool Context::deactivateAnonymousNamespace() {
return true;
}

void Context::activateFunctionScope(Function *fn) {
active_function_scopes.push_back(fn);
}

void Context::deactivateFunctionScope(Function *fn) {
assert((active_function_scopes.size() &&
active_function_scopes.back() == fn)
&& "unmatched function scope");
active_function_scopes.pop_back();
}

Function *Context::getCurrentFunctionScope() {
if (!active_function_scopes.size()) return NULL;
return active_function_scopes.back();
}

NSNode *getNSNodeFromNode(std::vector<std::string> *ns_parts,
NSNode *current) {
for (std::vector<std::string>::iterator b = ns_parts->begin(),
Expand Down Expand Up @@ -471,7 +451,12 @@ Function *Context::getFunction(const char *name,
return NULL;
}

Variable *Context::getVariable(const char *name) {
bool Context::addVariable(const char* name, Variable *var) {
var->fn = getCurrentFunctionScope();
return ns()->addVariable(name, var);
}

Variable* Context::getVariableInner(const char *name) {
if (strchr(name, '.')) {
Namespace *ns = getNamespace(name, true);
if (!ns) {
Expand Down Expand Up @@ -501,6 +486,15 @@ Variable *Context::getVariable(const char *name) {
return NULL;
}

Variable *Context::getVariable(const char *name) {
Variable *ret = getVariableInner(name);
if (ret && ret->fn && ret->fn != getCurrentFunctionScope()) {
// the variable can't be referenced as a value
return NULL;
}
return ret;
}

Struct *Context::getStruct(const char *name) {
if (strchr(name, '.')) {
Namespace *ns = getNamespace(name, true);
Expand Down
37 changes: 29 additions & 8 deletions src/dale/Context/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ class Context {
std::vector<Variable *> retrieved_var;
/*! Functions that have been retrieved. */
std::vector<Function *> retrieved_fn;
/*! Active function scopes. It will be an empty vector for global
* variables. */
std::vector<Function *> active_function_scopes;

Variable *getVariableInner(const char *name);

public:
/*! The native types for the context. Used primarily for type
Expand Down Expand Up @@ -87,12 +92,6 @@ class Context {
/*! Get the currently-active namespace.
*/
Namespace *ns();
/*! Pop active namespaces until the given namespace has been
* reached. Does the same thing for used namespaces, save that
* only anonymous namespaces are removed.
* @param ns The namespace that needs to be reached.
*/
bool popUntilNamespace(Namespace *ns);

/*! Activate the namespace with the given name.
* @param name The name of the namespace.
Expand Down Expand Up @@ -135,6 +134,24 @@ class Context {
*/
bool deactivateAnonymousNamespace();

/*! Activate a function scope.
*
* The function scopes is a set of scopes parallel to namespaces,
* and used to catch invalid variable references to a local
* variable in a different function.
* @param fn The new function scope.
*/
void activateFunctionScope(Function *fn);
/*! Deactivate the current function scope.
* @param fn The function scope to deactivate.
*/
void deactivateFunctionScope(Function *fn);
/*! Get the current active function scope.
* @return Returns NULL, if currently it's outside of any function
* scope (i.e. the function scope of global variables).
*/
Function *getCurrentFunctionScope();

/*! Retrieve a namespace node by name.
* @param name The name of the namespace.
* @param ignore_last Whether to ignore the last segment of the
Expand Down Expand Up @@ -200,10 +217,14 @@ class Context {
Function **closest_fn, bool is_macro,
std::vector<bool> *lvalues = NULL,
std::vector<Type *> *array_types = NULL);
/*! Add a variable to the current active namespace and with the
* current active function scope. */
bool addVariable(const char *name, Variable *var);
/*! Get the variable with the given name.
*
* See Namespace::getVariable. As per getFunction, this iterates
* over the used namespaces, calling that method.
* See Namespace::getVariable. As per getFunction, this iterates
* over the used namespaces, calling that method. This also takes
* care of function scopes.
*/
Variable *getVariable(const char *name);
/*! Get the struct with the given name.
Expand Down
2 changes: 1 addition & 1 deletion src/dale/ErrorType/ErrorType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const char *errorInstanceToString(int error_instance) {
ret = "not in scope: '%s'";
break;
case ErrorInst::VariableNotInScope:
ret = "variable not in scope: '%s'";
ret = "variable not in scope or cannot be used as value: '%s'";
break;
case ErrorInst::UnexpectedElement:
ret = "expected %s for %s (got %s instead)";
Expand Down
7 changes: 1 addition & 6 deletions src/dale/Form/Function/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ Type *parseReturnType(Units *units, Context *ctx,
for (std::vector<Variable *>::iterator b = parameters->begin(),
e = parameters->end();
b != e; ++b) {
ctx->ns()->addVariable((*b)->name.c_str(), (*b));
ctx->addVariable((*b)->name.c_str(), (*b));
}

Type *ret_type =
Expand Down Expand Up @@ -473,9 +473,6 @@ bool FormFunctionParse(Units *units, Node *node, const char *name,
return true;
}

ctx->activateAnonymousNamespace();
std::string anon_name = ctx->ns()->name;

units->top()->pushGlobalFunction(fn);
FormProcBodyParse(units, node, fn, llvm_fn, (next_index + 2),
is_anonymous, llvm_return_value);
Expand All @@ -488,8 +485,6 @@ bool FormFunctionParse(Units *units, Node *node, const char *name,
addInitChannelsCall(ctx, llvm_fn);
}

ctx->deactivateNamespace(anon_name.c_str());

if (units->debug) {
moduleDebugPass(units->top()->module);
}
Expand Down
18 changes: 3 additions & 15 deletions src/dale/Form/Proc/Def/Def.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,10 @@ bool typeRequiresExplicitInit(Context *ctx, Type *type) {

llvm::Constant *parseGlobalLiteral(Units *units, Type *type,
Node *node) {
Context *ctx = units->top()->ctx;

std::vector<NSNode *> active_ns_nodes = ctx->active_ns_nodes;
std::vector<NSNode *> used_ns_nodes = ctx->used_ns_nodes;
if (!units->prefunction_ns) {
units->prefunction_ns = ctx->active_ns_nodes.front()->ns;
}
ctx->popUntilNamespace(units->prefunction_ns);

llvm::Constant *init = NULL;
int size;
init = FormValueParse(units, type, node, &size);

ctx->active_ns_nodes = active_ns_nodes;
ctx->used_ns_nodes = used_ns_nodes;

return init;
}

Expand Down Expand Up @@ -242,7 +230,7 @@ bool parseImplicitVarDefinition(Units *units, Function *fn,
llvm::cast<llvm::Value>(builder.CreateAlloca(llvm_type));
var->value = dst_ptr;

res = ctx->ns()->addVariable(name, var);
res = ctx->addVariable(name, var);
if (!res) {
Error *e = new Error(RedefinitionOfVariable, node, name);
ctx->er->addError(e);
Expand Down Expand Up @@ -313,7 +301,7 @@ bool parseExplicitVarDefinition(Units *units, Function *fn,
var->value = dst_ptr;
var->linkage = linkage;

bool res = ctx->ns()->addVariable(name, var);
bool res = ctx->addVariable(name, var);
if (!res) {
Error *e = new Error(RedefinitionOfVariable, node, name);
ctx->er->addError(e);
Expand Down Expand Up @@ -440,7 +428,7 @@ bool parseExplicitVarDefinition(Units *units, Function *fn,

llvm_var->setInitializer(init);

bool res = ctx->ns()->addVariable(name, var);
bool res = ctx->addVariable(name, var);
if (!res) {
Error *e = new Error(RedefinitionOfVariable, node, name);
ctx->er->addError(e);
Expand Down
12 changes: 0 additions & 12 deletions src/dale/Form/Proc/Inst/Inst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ bool createAnonymousFunction(Units *units, llvm::BasicBlock *block,
Context *ctx = units->top()->ctx;
int preindex = ctx->lv_index;

std::vector<NSNode *> active_ns_nodes = ctx->active_ns_nodes;
std::vector<NSNode *> used_ns_nodes = ctx->used_ns_nodes;
if (!units->prefunction_ns) {
units->prefunction_ns = ctx->active_ns_nodes.front()->ns;
}
ctx->popUntilNamespace(units->prefunction_ns);

int error_count_begin =
ctx->er->getErrorTypeCount(ErrorType::Error);

Expand All @@ -49,8 +42,6 @@ bool createAnonymousFunction(Units *units, llvm::BasicBlock *block,
int error_count_end = ctx->er->getErrorTypeCount(ErrorType::Error);

if (error_count_begin != error_count_end) {
ctx->active_ns_nodes = active_ns_nodes;
ctx->used_ns_nodes = used_ns_nodes;
return false;
}

Expand All @@ -76,9 +67,6 @@ bool createAnonymousFunction(Units *units, llvm::BasicBlock *block,
(*b)->index = 0;
}

ctx->active_ns_nodes = active_ns_nodes;
ctx->used_ns_nodes = used_ns_nodes;

return true;
}

Expand Down
27 changes: 22 additions & 5 deletions src/dale/Form/ProcBody/ProcBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ bool addVariables(Context *ctx, Node *node, Function *fn,
}
}
bool res =
ctx->ns()->addVariable(param_var->name.c_str(), param_var);
ctx->addVariable(param_var->name.c_str(), param_var);
if (!res) {
Error *e = new Error(RedefinitionOfVariable, node,
param_var->name.c_str());
Expand Down Expand Up @@ -105,7 +105,7 @@ bool addRetval(Context *ctx, Node *node, Function *fn,
var->index = 0;
var->linkage = Linkage::Auto;

bool res = ctx->ns()->addVariable(var->name.c_str(), var);
bool res = ctx->addVariable(var->name.c_str(), var);
if (!res) {
Error *e =
new Error(RedefinitionOfVariable, node, var->name.c_str());
Expand Down Expand Up @@ -330,9 +330,9 @@ void removePostTerminators(llvm::Function *llvm_fn) {
}
}

bool FormProcBodyParse(Units *units, Node *node, Function *fn,
llvm::Function *llvm_fn, int skip,
bool is_anonymous, llvm::Value *return_value) {
static bool FormProcBodyParseInner(Units *units, Node *node, Function *fn,
llvm::Function *llvm_fn, int skip,
bool is_anonymous, llvm::Value *return_value) {
Context *ctx = units->top()->ctx;

std::vector<Node *> *lst = node->list;
Expand Down Expand Up @@ -405,4 +405,21 @@ bool FormProcBodyParse(Units *units, Node *node, Function *fn,

return true;
}

bool FormProcBodyParse(Units *units, Node *node, Function *fn,
llvm::Function *llvm_fn, int skip,
bool is_anonymous, llvm::Value *return_value) {
Context *ctx = units->top()->ctx;
ctx->activateAnonymousNamespace();
std::string anon_name = ctx->ns()->name;
ctx->activateFunctionScope(fn);

bool ret = FormProcBodyParseInner(units, node, fn, llvm_fn, skip, is_anonymous, return_value);

ctx->deactivateFunctionScope(fn);
ctx->deactivateNamespace(anon_name.c_str());

return ret;
}

}
2 changes: 1 addition & 1 deletion src/dale/Form/TopLevel/GlobalVariable/GlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ bool FormTopLevelGlobalVariableParse(Units *units, Node *node,
var->once_tag = units->top()->once_tag;
var->linkage = linkage;

bool res = ctx->ns()->addVariable(name, var);
bool res = ctx->addVariable(name, var);
if (!res) {
Error *e = new Error(RedefinitionOfVariable, def_node, name);
ctx->er->addError(e);
Expand Down
3 changes: 0 additions & 3 deletions src/dale/Form/TopLevel/Macro/Macro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,9 @@ bool FormTopLevelMacroParse(Units *units, Node *node,
int error_count_begin =
ctx->er->getErrorTypeCount(ErrorType::Error);

ctx->activateAnonymousNamespace();
std::string anon_name = ctx->ns()->name;
units->top()->pushGlobalFunction(fn);
FormProcBodyParse(units, top, fn, llvm_fn, 3, 0);
units->top()->popGlobalFunction();
ctx->deactivateNamespace(anon_name.c_str());

int error_count_end = ctx->er->getErrorTypeCount(ErrorType::Error);

Expand Down
13 changes: 0 additions & 13 deletions src/dale/Form/Value/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,10 @@ bool parseFunction(Units *units, Type *type, Node *top, Function *fn) {
nodes.push_back(top);
Node *copy_top = new Node(&nodes);

std::vector<NSNode *> active_ns_nodes = ctx->active_ns_nodes;
std::vector<NSNode *> used_ns_nodes = ctx->used_ns_nodes;
if (!units->prefunction_ns) {
units->prefunction_ns = ctx->active_ns_nodes.front()->ns;
}
ctx->popUntilNamespace(units->prefunction_ns);

units->top()->pushGlobalFunction(fn);
ctx->activateAnonymousNamespace();
std::string anon_name = ctx->ns()->name;
FormProcBodyParse(units, copy_top, fn, llvm_fn, 0, 0);
ctx->deactivateNamespace(anon_name.c_str());
units->top()->popGlobalFunction();

ctx->active_ns_nodes = active_ns_nodes;
ctx->used_ns_nodes = used_ns_nodes;

int error_count_end = ctx->er->getErrorTypeCount(ErrorType::Error);
if (error_count_begin != error_count_end) {
llvm_fn->replaceAllUsesWith(
Expand Down
Loading