M src/backends/LLVMCompiler.cpp +6 -4
@@ 575,10 575,12 @@ namespace K3 {
llvm::Value* ptr = b.CreateLoad(ptrPtr);
if (lt.IsInitPass()) {
if (GetUp(0)) {
- llvm::Value* init = lt(GetUp(0));
- ptr = b.CreateSelect(
- b.CreateICmpNE(ptr, Constant::getNullValue(ptr->getType())), ptr, init);
- b.CreateStore(ptr, ptrPtr);
+ if (!IsNil(GetUp(0))) {
+ llvm::Value* init = lt(GetUp(0));
+ ptr = b.CreateSelect(
+ b.CreateICmpNE(ptr, Constant::getNullValue(ptr->getType())), ptr, init);
+ b.CreateStore(ptr, ptrPtr);
+ }
} else {
auto fn = lt.GetModule()->getOrInsertFunction("GetConfigurationSlot",
llvm::FunctionType::get(lt.GetBuilder().getInt8PtrTy(), { lt.GetBuilder().getInt32Ty() }, false));
M src/backends/SideEffectCompiler.cpp +3 -1
@@ 1576,7 1576,9 @@ namespace K3
auto buf = Buffer::New(sfx, Native::Constant::New(int64_t(t.GetSize())), Buffer::Module, 16);
initializer = Deps::New(buf, sfx.CopyData(DataSource::New(buf, layout), initializer,
sfx.GetSymbolTable().GetInitializerReactivity(), true, true, true));
- }
+ } else {
+ initializer = Typed::Nil();
+ }
if (key.IsNil() == false) {
sfx.GetSymbolTable().RegisterExternalVariable(key, t, uid, k, vectorRate, clock);
M src/k3/DynamicVariables.cpp +13 -0
@@ 37,6 37,19 @@ namespace K3 {
Specialization GenericExternalVariable::Specialize(SpecializationState& spec) const {
SPECIALIZE(spec, key, GetUp(0));
SPECIALIZE(spec, init, GetUp(1));
+
+ if (unsafe) {
+ auto initType = init.result.Fix();
+
+ return Specialization(
+ GetGlobalVariable::New(TLS::GetCurrentInstance()->Memoize(key.result.Fix()),
+ initType,
+ key.result.Fix(),
+ std::make_pair(1,1),
+ nullptr,
+ External),
+ initType);
+ }
if (spec.mode == SpecializationState::Configuration) {
return init;
M src/k3/DynamicVariables.h +3 -2
@@ 93,9 93,10 @@ namespace K3 {
END
GENERIC_NODE(GenericExternalVariable,GenericBinary)
- GenericExternalVariable(CGRef key, CGRef initializer):GenericBinary(key,initializer){}
+ bool unsafe;
+ GenericExternalVariable(CGRef key, CGRef initializer,bool unsafe):GenericBinary(key,initializer), unsafe(unsafe) { }
PUBLIC
- static GenericExternalVariable* New(CGRef key, CGRef initializer) {return new GenericExternalVariable(key,initializer);}
+ static GenericExternalVariable* New(CGRef key, CGRef initializer, bool unsafe) {return new GenericExternalVariable(key,initializer,unsafe);}
END
GENERIC_NODE(GenericStreamInput,GenericTernary)
M src/k3/TLS.cpp +4 -1
@@ 16,6 16,8 @@
#include <locale>
#include <regex>
#include <iostream>
+#include <functional>
+#include <utility>
#ifdef HAVE_LLVM
#pragma warning(disable: 4126 4267)
@@ 56,7 58,8 @@ namespace K3 {
build.AddFunction("Eval", Nodes::Evaluate::New("eval", b1, b2), "fn arg...", "Evaluates 'fn' as a function with the arguments in 'arg...'");
- build.AddFunction("External", Nodes::GenericExternalVariable::New(b1, b2), "key default", "External input declaration with the identifier 'key' and type and default value provided by 'default'");
+ build.AddFunction("External", Nodes::GenericExternalVariable::New(b1, b2, false), "key default", "External input declaration with the identifier 'key' and type and default value provided by 'default'");
+ build.AddFunction("External-Unsafe", Nodes::GenericExternalVariable::New(b1, b2, true), "key default", "External input declaration with the identifier 'key' and type and default value provided by 'default'. The input will not be initialized and must be bound by whomever uses the circuit, before invoking any code that touches the value.");
build.AddFunction("External-Stream", Nodes::GenericStreamInput::New(b1, Nodes::GenericFirst::New(b2), Nodes::GenericRest::New(b2)), "stream-key default clock", "Stream input to this module from an external vector. The sample rate of the buffer is determined by 'clock'.");
build.AddFunction("External-Asset", Nodes::GenericAsset::New(arg), "uri", "Loads an asset from 'uri' and returns its contents.");
build.AddMacro("Audio-File-Tag", Nodes::Invariant::Constant::New(Type(&AudioFileTag)), true);