Skip to content

Commit

Permalink
[master] allow copying to be disabled for a type (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhrr committed Mar 19, 2016
1 parent aebdaf4 commit c1aa252
Show file tree
Hide file tree
Showing 13 changed files with 181 additions and 34 deletions.
3 changes: 3 additions & 0 deletions src/dale/ErrorType/ErrorType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ errorInstanceToString(int error_instance)
case ErrorInst::SetfOverridesMustReturnBool:
ret = "setf overrides must return bool";
break;
case ErrorInst::CopyDisabled:
ret = "copying is disabled for this type";
break;
case ErrorInst::RefsNotPermittedHere:
ret = "reference types not permitted in this context";
break;
Expand Down
1 change: 1 addition & 0 deletions src/dale/ErrorType/ErrorType.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ enum
ZeroLengthGlobalArraysAreUnsupported,
CannotModifyConstVariable,
SetfOverridesMustReturnBool,
CopyDisabled,
RefsNotPermittedHere,
RetvalsNotPermittedHere,

Expand Down
11 changes: 10 additions & 1 deletion src/dale/Form/Proc/Def/Def.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ storeValue(Context *ctx, Node *node, Type *type,
ctx->getFunction("setf-move-init", &param_types, NULL, false,
&lvalues);

if (or_setf_move) {
if (or_setf_move && !pr->value_is_lvalue) {
std::vector<llvm::Value *> call_args;
call_args.push_back(dst_ptr);

Expand All @@ -126,6 +126,15 @@ storeValue(Context *ctx, Node *node, Type *type,
return true;
}

/* If this not something that can be copied, return an error message. */
std::vector<Type *> disabled_types;
disabled_types.push_back(type);
if (ctx->getFunction("setf-copy-disabled", &disabled_types, NULL, 0)) {
Error *e = new Error(ErrorInst::CopyDisabled, node);
ctx->er->addError(e);
return false;
}

param_types.pop_back();
param_types.push_back(ctx->tr->getPointerType(type));
Function *or_setf =
Expand Down
2 changes: 1 addition & 1 deletion src/dale/Form/Proc/Inst/Inst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ FormProcInstParse(Units *units, Function *fn, llvm::BasicBlock *block,
return true;
}
if (!no_copy) {
Operation::Copy(units->top()->ctx, fn, pr, pr);
Operation::Copy(units->top()->ctx, fn, node, pr, pr);
}

return true;
Expand Down
9 changes: 9 additions & 0 deletions src/dale/Form/Proc/Setf/Setf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,15 @@ FormProcSetfParse(Units *units, Function *fn, llvm::BasicBlock *block,
}
}

/* If this not something that can be copied, return an error message. */
std::vector<Type *> disabled_types;
disabled_types.push_back(variable_pr.type->points_to);
if (ctx->getFunction("setf-copy-disabled", &disabled_types, NULL, 0)) {
Error *e = new Error(ErrorInst::CopyDisabled, node);
ctx->er->addError(e);
return false;
}

/* If an overridden setf exists, and value_pr is a value of the
* pointee type of variable_pr, then call the overridden setf
* after allocating memory for value_pr and copying it into place.
Expand Down
8 changes: 8 additions & 0 deletions src/dale/Form/TopLevel/GlobalVariable/GlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,16 @@ parseLiteral(Units *units, Type *type, Node *top, int *size)
NULL, false, &lvalues);
Function *or_setf = ctx->getFunction("setf-copy-assign", &call_arg_types,
NULL, 0);
std::vector<Type *> disabled_types;
disabled_types.push_back(type);

if (or_move && is_rvalue) {
or_setf = or_move;
} else if (ctx->getFunction("setf-copy-disabled", &disabled_types,
NULL, 0)) {
Error *e = new Error(ErrorInst::CopyDisabled, top);
ctx->er->addError(e);
return NULL;
}

if (or_setf) {
Expand Down
1 change: 1 addition & 0 deletions src/dale/Form/Utils/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ FormProcessValue(Units *units, Function *fn, llvm::BasicBlock *block,
var_value_node->token->str_value.c_str()))) {
pr->set(block, var_value->type,
builder.CreateLoad(var_value->value));
pr->value_is_lvalue = true;
pr->do_not_destruct = true;
} else if (var_value_node->is_list
&& (var_value_node_list->size() == 2)
Expand Down
58 changes: 30 additions & 28 deletions src/dale/FunctionProcessor/FunctionProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,41 +122,43 @@ processReferenceTypes(std::vector<llvm::Value *> *call_args,
}
(*call_args_final)[i] = refpr.getValue(ctx);
} else {
std::vector<Type *> param_types;
param_types.push_back(ctx->tr->getPointerType(pt));
param_types.push_back(pt);
std::vector<bool> lvalues;
lvalues.push_back(true);
lvalues.push_back(false);
Function *or_setf_move =
ctx->getFunction("setf-move-init", &param_types, NULL, false,
&lvalues);

if (!arg_refpr->value_is_lvalue && or_setf_move) {
std::vector<Type *> param_types;
param_types.push_back(ctx->tr->getPointerType(pt));
param_types.push_back(pt);
std::vector<bool> lvalues;
lvalues.push_back(true);
lvalues.push_back(false);
Function *or_setf_move =
ctx->getFunction("setf-move-init", &param_types, NULL, false,
&lvalues);

if (!arg_refpr->value_is_lvalue && or_setf_move) {
llvm::IRBuilder<> builder(arg_refpr->block);
std::vector<llvm::Value *> or_call_args;
llvm::Value *dst_ptr =
llvm::cast<llvm::Value>(
builder.CreateAlloca(ctx->toLLVMType(pt, NULL,
false, false))
);
or_call_args.push_back(dst_ptr);
std::vector<llvm::Value *> or_call_args;
llvm::Value *dst_ptr =
llvm::cast<llvm::Value>(
builder.CreateAlloca(ctx->toLLVMType(pt, NULL,
false, false))
);
or_call_args.push_back(dst_ptr);
bool res = arg_refpr->getAddressOfValue(ctx, &refpr);
if (!res) {
return false;
}
or_call_args.push_back(refpr.getValue(ctx));
or_call_args.push_back(refpr.getValue(ctx));

builder.CreateCall(or_setf_move->llvm_function,
llvm::ArrayRef<llvm::Value*>(or_call_args));
builder.CreateCall(or_setf_move->llvm_function,
llvm::ArrayRef<llvm::Value*>(or_call_args));
(*call_args_final)[i] = builder.CreateLoad(dst_ptr);
} else if (!args_cast) {
bool res = Operation::Copy(ctx, dfn, arg_refpr, arg_refpr);
if (!res) {
return false;
}
(*call_args_final)[i] = arg_refpr->getValue(ctx);
}
} else if (!args_cast) {
bool res = Operation::Copy(ctx, dfn,
(*call_arg_nodes)[i],
arg_refpr, arg_refpr);
if (!res) {
return false;
}
(*call_args_final)[i] = arg_refpr->getValue(ctx);
}
}
}

Expand Down
15 changes: 13 additions & 2 deletions src/dale/Operation/Copy/Copy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace dale
namespace Operation
{
bool
Copy(Context *ctx, Function *fn, ParseResult *pr, ParseResult *ret_pr)
Copy(Context *ctx, Function *fn, Node *node, ParseResult *pr,
ParseResult *ret_pr)
{
pr->copyTo(ret_pr);

Expand All @@ -29,11 +30,21 @@ Copy(Context *ctx, Function *fn, ParseResult *pr, ParseResult *ret_pr)
return true;
}

/* If this not something that can be copied, return an error
* message. */
std::vector<Type *> disabled_types;
disabled_types.push_back(pr->type);
if (ctx->getFunction("setf-copy-disabled", &disabled_types, NULL, 0)) {
Error *e = new Error(ErrorInst::CopyDisabled, node);
ctx->er->addError(e);
return false;
}

Type *copy_type = ctx->tr->getPointerType(pr->type);
std::vector<Type *> types;
types.push_back(copy_type);
types.push_back(copy_type);
Function *over_setf = ctx->getFunction("setf-copy-init", &types, NULL, 0);
Function *over_setf = ctx->getFunction("setf-copy-init", &types, NULL, false);
if (!over_setf) {
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/dale/Operation/Copy/Copy.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ namespace Operation
/*! Copy a parsed value, if required.
* @param ctx The current context.
* @param fn The current function.
* @param node The node of the value being copied.
* @param value_pr The parse result containing the value to be copied.
* @param pr The parse result into which the result should be put.
*/
bool Copy(Context *ctx, Function *fn, ParseResult *value_pr,
bool Copy(Context *ctx, Function *fn, Node *node, ParseResult *value_pr,
ParseResult *pr);
}
}
Expand Down
2 changes: 1 addition & 1 deletion t/999last/001compile-errors.t
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ $ENV{"DALE_TEST_ARGS"} ||= "";
my $test_dir = $ENV{"DALE_TEST_DIR"} || ".";
$ENV{PATH} .= ":.";

use Test::More tests => 204;
use Test::More tests => 209;

my @error_files =
(@ARGV)
Expand Down
98 changes: 98 additions & 0 deletions t/error-src/setf-copy-disabled.dt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
(import cstdio)

(def mys (struct intern ((a int) (b int))))

(def init
(fn intern bool ((dst (ref mys)) (a int) (b int))
(setf (:@ dst a) a)
(setf (:@ dst b) b)
true))

(def mys-copy (fn intern bool ((dst (p mys)) (src (p mys)))
(setf (:@ dst a) (@:@ src a))
(setf (:@ dst b) (@:@ src b))
true))

(def setf-copy-init (fn intern bool ((dst (p mys)) (src (p mys)))
(printf "setf-copy-init\n")
(mys-copy dst src)))

(def setf-copy-assign (fn intern bool ((dst (p mys)) (src (p mys)))
(printf "setf-copy-assign\n")
(mys-copy dst src)))

(def setf-copy-disabled (fn intern void ((dst mys))))

(def mys-move (fn intern bool ((dst (p mys)) (src (rv-ref mys)))
(setf (:@ dst a) (@:@ src a))
(setf (:@ dst b) (@:@ src b))
true))

(def setf-move-init (fn intern bool ((dst (p mys)) (src (rv-ref mys)))
(printf "setf-move-init\n")
(mys-move dst (move (@ src)))))

(def setf-move-assign (fn intern bool ((dst (p mys)) (src (rv-ref mys)))
(printf "setf-move-assign\n")
(mys-move dst (move (@ src)))))

;(def swap (fn extern void ((a (ref mys))
; (b (ref mys)))
; (let ((temp \ (move (@ a))))
; (setf a (move (@ b)))
; (setf b (move temp))
; (return))))

; Calling this function should cause no copies to occur.
(def swap (fn extern void ((a (rv-ref mys))
(b (rv-ref mys)))
(let ((temp \ (move (@ a))))
(setf a (move (@ b)))
(setf b (move temp))
(return))))

; Calling this function should cause a single setf-move-init to occur.
(def rv-ref-use (fn intern bool ((n (rv-ref mys)))
(def d (var auto mys (move (@ n))))
true))

; Calling this function with an rvalue reference should cause two
; setf-move-inits to occur.
(def rv-ref-use2 (fn intern bool ((n mys))
(def d (var auto mys (move n)))
true))

(def ga (var intern mys))
(def gb (var intern mys ga))

(def main (fn extern-c int (void)
(def a (var auto mys (init a 1 2)))
(def b (var auto mys (init b 1 3)))

(def g (var auto mys))
(setv g b)

(def f (var auto mys b))
(rv-ref-use2 b)

(printf "Previously: two setf-move-inits\n")
(printf "One setf-move-init\n")
(def c (var auto mys (move a)))
(printf "One setf-move-assign\n")
(setv c (move b))
(printf "One setf-move-init\n")
(rv-ref-use (move c))

(def e (var auto mys (init e 1 4)))
(printf "Two setf-move-inits\n")
(rv-ref-use2 (move e))

(printf "Preswap\n")
(printf "%d %d\n" (@: a a) (@: a b))
(printf "%d %d\n" (@: b a) (@: b b))

(swap (move a) (move b))
(printf "Postswap\n")
(printf "%d %d\n" (@: a a) (@: a b))
(printf "%d %d\n" (@: b a) (@: b b))
0))
4 changes: 4 additions & 0 deletions t/error-src/setf-copy-disabled.dt.errors
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
./t/error-src/setf-copy-disabled.dt:66:25: error: copying is disabled for this type
./t/error-src/setf-copy-disabled.dt:73:3: error: copying is disabled for this type
./t/error-src/setf-copy-disabled.dt:75:3: error: copying is disabled for this type
./t/error-src/setf-copy-disabled.dt:76:16: error: copying is disabled for this type

0 comments on commit c1aa252

Please sign in to comment.