M .hgsubstate +2 -2
@@ 1,5 1,5 @@
-c1bcc6e5a506ee98223a58316481e1b775153c02 editors/st3
-e7b9b9118a609b6b283ee8d6845a16b08079f649 library
+6b1b48369d48250bfea95217cd08253cc5b43d71 editors/st3
+c7e2fdabbb72b80f6d1f880eda7956cd0f517546 library
19292d513d74939f058a037bbc5ea0ccd6acbc98 src/lithe
c3e562558279e535531dd37f3c2b2770e49000d9 src/pad
adf19f7ab6aa4d8bac58329c887eb210b1464f3d src/paf
M editors/kronos.natvis +2 -1
@@ 113,7 113,7 @@
<Type Name="K3::Nodes::SubroutineArgument">
<DisplayString>ARG{ID}</DisplayString>
</Type>
- <Type Name="K3::Nodes::Monad">
+ <Type Name="K3::Nodes::Deps">
<DisplayString>Proc( {*upstream[0]} )</DisplayString>
<Expand>
<Item Name="Value">*upstream[0]</Item>
@@ 220,6 220,7 @@
<Item Name="Source">*upstream[1]</Item>
<Item Name="Size">*upstream[2]</Item>
<Item Name="Clock" Condition="reactivity != nullptr">*reactivity</Item>
+ <Item Name="Repeat">*upstream[3]</Item>
</Expand>
</Type>
<Type Name="K3::Nodes::Boundary">
M src/backends/BinaryenCompiler.cpp +8 -2
@@ 17,6 17,7 @@ namespace K3 {
else if (t.IsFloat64()) return xfm.Float64Ty();
else if (t.IsInt32()) return xfm.Int32Ty();
else if (t.IsInt64()) return xfm.Int64Ty();
+ else if (t.IsArrayView()) return xfm.PtrTy();
INTERNAL_ERROR("Illegal unlowered type in generic codegen");
}
@@ 125,7 126,7 @@ namespace K3 {
return xfm->SizeOfPointer();
}
- CODEGEN_EMIT(Monad) {
+ CODEGEN_EMIT(Deps) {
return xfm(GetUp(0));
}
@@ 188,9 189,14 @@ namespace K3 {
CODEGEN_EMIT(Buffer) {
switch (alloc) {
case Stack:
+ case StackZeroed:
{
auto sz{ xfm(GetUp(0)) };
- return xfm->Alloca(sz, alignment);
+ auto buf = xfm->Alloca(sz, alignment);
+ if (alloc == StackZeroed) {
+ xfm->MemSet(buf, xfm->Const(0), sz);
+ }
+ return buf;
}
case Module:
{
M src/backends/BinaryenEmitter.h +1 -0
@@ 181,6 181,7 @@ namespace K3 {
}
BinaryenExpressionRef Const(PortableSize psz) {
+ assert(0 && "add config slots");
return Const((int)(psz.byteCount + psz.pointerCount * 4));
}
M src/backends/CodeGenCompiler.cpp +83 -9
@@ 134,7 134,7 @@ namespace K3 {
Buffer *b;
if (node->Cast(b) && b->GetAllocation() == Buffer::Stack) return true;
- if (IsOfExactType<Monad>(node) ||
+ if (IsOfExactType<Deps>(node) ||
IsOfExactType<Offset>(node) ||
IsOfExactType<Dereference>(node) ||
IsOfExactType<Reference>(node)) {
@@ 191,16 191,16 @@ namespace K3 {
assert(free.empty() == false); // assume at least one schedulable node
#ifndef NDEBUG
- unsigned numMonads(0);
+ unsigned numDepsNodes = 0;
#endif
while (free.empty() == false) {
const SchedulingUnit *next = *free.begin();
free.erase(free.begin());
- if (IsOfExactType<Monad>(get<0>(*next)) == false)
+ if (IsOfExactType<Deps>(get<0>(*next)) == false)
schedule.push_back(*next);
#ifndef NDEBUG
else
- numMonads++;
+ numDepsNodes++;
#endif
auto deps(edges.equal_range(get<0>(*next)));
@@ 210,18 210,49 @@ namespace K3 {
}
}
#ifndef NDEBUG
- assert(schedule.size() + numMonads == units.size() && "Unscheduled nodes found");
+ assert(schedule.size() + numDepsNodes == units.size() && "Unscheduled nodes found");
#endif
return schedule;
}
}
PortableSize operator+(PortableSize a, PortableSize b) {
- return { a.pointerCount + b.pointerCount, a.byteCount + b.byteCount };
+ a.pointerCount += b.pointerCount;
+ a.byteCount += b.byteCount;
+ for (auto &slot : b.configSlotCount) {
+ a.configSlotCount[slot.first] += slot.second;
+ }
+ return a;
}
PortableSize operator*(PortableSize a, int b) {
- return { a.pointerCount * b, a.byteCount * b };
+ a.pointerCount *= b;
+ a.byteCount *= b;
+ for (auto &slot : a.configSlotCount) {
+ slot.second *= b;
+ }
+ return a;
+ }
+
+ PortableSize operator>>(PortableSize a, int b) {
+ a.pointerCount >>= b;
+ a.byteCount >>= b;
+ for (auto &slot : a.configSlotCount) {
+ slot.second >>= b;
+ }
+ return a;
+ }
+
+ PortableSize Max(PortableSize a, PortableSize b) {
+ if (b.pointerCount > a.pointerCount) a.pointerCount = b.pointerCount;
+ if (b.byteCount > a.byteCount) a.byteCount = b.byteCount;
+ for (auto & slot : a.configSlotCount) {
+ slot.second = std::max(slot.second, b.configSlotCount[slot.first]);
+ }
+ for (auto & slot : b.configSlotCount) {
+ a.configSlotCount[slot.first] = std::max(slot.second, a.configSlotCount[slot.first]);
+ }
+ return a;
}
PortableSize SizingTransform::operate(CTRef n) {
@@ 229,9 260,10 @@ namespace K3 {
Offset* o;
SubroutineArgument *a;
SubroutineStateAllocation *sra;
- Monad *mn;
+ Deps *mn;
SubroutineMeta* mt;
SizeOfPointer* szp;
+ Copy* cpy;
Native::Constant* c;
if (n->Cast(mn) || n->Cast(mt)) {
@@ 258,7 290,7 @@ namespace K3 {
}
if (n->Cast(a)) {
assert(a->IsState());
- return { 0,0 };
+ return { 0, 0 };
}
if (n->Cast(c)) {
if (c->FixedResult().IsInt32()) {
@@ 271,6 303,48 @@ namespace K3 {
if (n->Cast(szp)) {
return { 1, 0 };
}
+ if (auto bin = n->Cast<Native::ITypedBinary>()) {
+ auto a = (*this)(n->GetUp(0));
+ auto b = (*this)(n->GetUp(1));
+ switch (bin->GetOpcode()) {
+ case Native::Mul:
+ assert(b.pointerCount == 0);
+ assert(b.configSlotCount.empty());
+ return a * b.byteCount;
+ case Native::Add:
+ return a + b;
+ case Native::Max:
+ return Max(a, b);
+ case Native::BitShiftRight:
+ assert(b.pointerCount == 0);
+ assert(b.configSlotCount.empty());
+ return a >> b.byteCount;
+ break;
+ default:
+ KRONOS_UNREACHABLE;
+ }
+ }
+ if (auto un = n->Cast<Native::ITypedUnary>()) {
+ auto a = (*this)(n->GetUp(0));
+ switch(un->GetOpcode()) {
+ case Native::ToInt64:
+ case Native::ToInt32:
+ return a;
+ default:
+ KRONOS_UNREACHABLE;
+ }
+ }
+ if (auto cfg = n->Cast<Configuration>()) {
+ PortableSize psz{ 0,0 };
+ psz.configSlotCount[cfg->GetSlotIndex()] = 1 << 24;
+ return psz;
+ }
+ if (n->Cast<Dereference>()) {
+ return (*this)(n->GetUp(0));
+ }
+ if (n->Cast(cpy)) {
+ return (*this)(cpy->GetUp(1));
+ }
KRONOS_UNREACHABLE;
}
}
No newline at end of file
M src/backends/CodeGenCompiler.h +1 -0
@@ 63,6 63,7 @@ namespace K3 {
struct PortableSize {
int64_t pointerCount;
int64_t byteCount;
+ std::unordered_map<int, int64_t> configSlotCount;
};
PortableSize operator*(PortableSize, int);
M src/backends/CodeMotionPass.cpp +2 -2
@@ 273,11 273,11 @@ namespace K3 {
}
Typed* CodeMotionPass::materializeVariables(CodeMotionPass& cmp, Typed* call) {
- Monad *variableMaterializer(0);
+ Deps *variableMaterializer(0);
for (auto var : cmp) {
if (materializeAll || variableBoundaries.find(var) != variableBoundaries.end()) {
if (variableMaterializer == 0) {
- variableMaterializer = Monad::New();
+ variableMaterializer = Deps::New();
variableMaterializer->Connect(call->GetUp(0));
}
variableMaterializer->Connect(SetGlobalVariable::New(var, var));
M src/backends/CopyElision.cpp +1 -1
@@ 83,7 83,7 @@ namespace K3 {
//sfx.SetArgumentElision(sfx.elision);
}
- void Monad::CopyElision(Backends::CopyElisionTransform& sfx) const
+ void Deps::CopyElision(Backends::CopyElisionTransform& sfx) const
{
if (GetNumCons()) sfx(GetUp(0));
}
M src/backends/LLVMCompiler.cpp +79 -20
@@ 99,7 99,21 @@ namespace K3 {
llvm::Value* LLVMTransform::ReifySize(llvm::IRBuilder<>& b, PortableSize ps) {
auto ptrSize = b.CreatePtrToInt(b.CreateConstGEP1_32(llvm::Constant::getNullValue(b.getInt8PtrTy()->getPointerTo()), ps.pointerCount), b.getInt64Ty());
- return b.CreateAdd(ConstantInt::get(b.getInt64Ty(), ps.byteCount), ptrSize);
+ auto sumSize = b.CreateAdd(ConstantInt::get(b.getInt64Ty(), ps.byteCount), ptrSize);
+ auto M = b.GetInsertBlock()->getParent()->getParent();
+ auto cfg = M->getOrInsertFunction(
+ "GetConfigurationSlot",
+ llvm::FunctionType::get(b.getInt8PtrTy(), { b.getInt32Ty() }, false));
+// return new LLVMSignal(lt.GetBuilder().CreateCall(fn, { lt.GetBuilder().getInt32(slotIndex) }));
+ for (auto &slot : ps.configSlotCount) {
+ auto cfgPtr = b.CreateCall(cfg, { b.getInt32(slot.first) });
+ llvm::Value* slotVal = b.CreateLoad(b.CreatePointerCast(cfgPtr, b.getFloatTy()->getPointerTo()));
+ slotVal = b.CreateFPToSI(slotVal, b.getInt64Ty());
+ slotVal = b.CreateMul(slotVal, b.getInt64(slot.second));
+ slotVal = b.CreateLShr(slotVal, 24);
+ sumSize = b.CreateAdd(sumSize, slotVal);
+ }
+ return sumSize;
}
LLVMTransform::LLVMTransform(ILLVMCompilationPass &comp) : CachedTransform(0), compilation(comp), bb(BasicBlock::Create(comp.GetContext(), "Top", function)), builder(bb),
@@ 517,17 531,31 @@ namespace K3 {
else return buf;
}
+ Ref<LLVMSignal> Configuration::Compile(LLVMTransform& lt, ActivityMaskVector *active) const {
+/* auto var = dyn_cast<GlobalVariable>(lt.GetModule()->getOrInsertGlobal("cfg_" + std::to_string(slotIndex), lt.GetType(ty)));
+ var->setLinkage(GlobalValue::AvailableExternallyLinkage);
+ return new LLVMSignal(lt.GetBuilder().CreateBitCast(var,lt.GetBuilder().getInt8PtrTy()));*/
+ auto fn = lt.GetModule()->getOrInsertFunction("GetConfigurationSlot", llvm::FunctionType::get(lt.GetBuilder().getInt8PtrTy(), { lt.GetBuilder().getInt32Ty() }, false));
+ return new LLVMSignal(lt.GetBuilder().CreateCall(fn, { lt.GetBuilder().getInt32(slotIndex) }));
+ }
+
Ref<LLVMSignal> GetSlot::Compile(LLVMTransform& lt, ActivityMaskVector* active) const {
auto &b{ lt.GetBuilder() };
auto self = lt.GetParameter(1);
self = b.CreateBitCast(self, b.getInt8PtrTy()->getPointerTo(), "slots");
auto ptrPtr = b.CreateConstGEP1_32(self, index, "slot");
llvm::Value* ptr = b.CreateLoad(ptrPtr);
- if (lt.IsInitPass() && GetNumCons()) {
- llvm::Value* init = *lt(GetUp(0));
- ptr = b.CreateSelect(
- b.CreateICmpNE(ptr, Constant::getNullValue(ptr->getType())), ptr, init);
- b.CreateStore(ptr, 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);
+ } else {
+ auto fn = lt.GetModule()->getOrInsertFunction("GetConfigurationSlot",
+ llvm::FunctionType::get(lt.GetBuilder().getInt8PtrTy(), { lt.GetBuilder().getInt32Ty() }, false));
+ return new LLVMSignal(lt.GetBuilder().CreateCall(fn, { lt.GetBuilder().getInt32(index) }));
+ }
}
return new LLVMSignal(ptr);
}
@@ 770,10 798,10 @@ namespace K3 {
return new LLVMSignal(b.CreatePtrToInt(onePtr, b.getInt64Ty()));
}
- Ref<LLVMSignal> Monad::Compile(LLVMTransform& lt, ActivityMaskVector* active) const {
+ Ref<LLVMSignal> Deps::Compile(LLVMTransform& lt, ActivityMaskVector* active) const {
auto a(lt(GetUp(0)));
//if (lt.IsInitPass()) {f
- // // init pass doesn't sort nodes, so monadic deps must be honred
+ // // init pass doesn't sort nodes, so Depsic deps must be honred
// for(unsigned i(GetNumCons()-1);i>0;--i) lt(GetUp(i));
//}
return a;
@@ 819,21 847,44 @@ namespace K3 {
llvm::Value *dst(*dstSig), *src(*srcSig), *elSz(*szSig);
dst = b.CreateBitCast(dst, b.getInt8PtrTy());
auto align = srcAlign && dstAlign ? AlignPowerOf2(-((-srcAlign) | (-dstAlign))) : 4;
- Ref<LLVMSignal> fst = new LLVMSignal(b.CreateMemCpy(dst, src, elSz, align));
- while (offset < repeat) {
- unsigned cpy = std::min(offset, unsigned(repeat - offset));
- auto sz(b.CreateMul(b.getInt32(cpy), elSz));
- auto subdst(b.CreateGEP(dst, b.CreateMul(b.getInt32(offset), elSz)));
- b.CreateMemCpy(subdst, dst, sz, align);
- offset += cpy;
+
+ // don't emit empty loops
+ int staticLoopCount = 999;
+ if (auto c = GetUp(3)->Cast<Native::Constant>()) {
+ if (staticLoopCount = *(int32_t*)c->GetPointer() < 1) {
+ break;
+ }
}
+
+ if (staticLoopCount > 1) {
+ auto loopCount = b.CreateSExt(*lt(GetUp(3), active), b.getInt64Ty());
+
+ auto priorBlock = b.GetInsertBlock();
+ auto loopBlock = llvm::BasicBlock::Create(b.getContext(), "initLoop", priorBlock->getParent());
+ auto nextBlock = llvm::BasicBlock::Create(b.getContext(), "endLoop", priorBlock->getParent());
+ b.CreateBr(loopBlock);
+ b.SetInsertPoint(loopBlock);
+
+ auto i = b.CreatePHI(b.getInt64Ty(), 2, "i");
+ auto nextI = b.CreateAdd(i, b.getInt64(1));
+ auto iDst = b.CreateGEP(dst, b.CreateMul(i, elSz));
+ i->addIncoming(b.getInt64(0), priorBlock);
+ i->addIncoming(nextI, loopBlock);
+ b.CreateMemCpy(b.CreateGEP(dst, b.CreateMul(i, elSz)), src, elSz, align);
+ b.CreateCondBr(b.CreateICmpNE(nextI, loopCount), loopBlock, nextBlock);
+
+ b.SetInsertPoint(nextBlock);
+ } else {
+ b.CreateMemCpy(dst, src, elSz, align);
+ }
+
break;
}
default:
INTERNAL_ERROR("Bad copy mode in LLVM backend");
}
}
- return Ref<LLVMSignal>();
+ return dstSig;
}
static llvm::Value* IsBufferBig(llvm::IRBuilder<>& b, llvm::Value* size) {
@@ 852,12 903,18 @@ namespace K3 {
switch (alloc) {
case Empty:
return new LLVMSignal(llvm::Constant::getNullValue(lt.GetBuilder().getInt8PtrTy()));
+ case StackZeroed:
case Stack:
- {
- auto sz = lt(GetUp(0));
- auto allocaed = lt.Alloca(GUID, *sz, alignment);
- return new LLVMSignal(allocaed);
+ {
+ auto sz = lt(GetUp(0));
+ auto allocaed = lt.Alloca(GUID, *sz, alignment);
+
+ if (alloc == StackZeroed) {
+ lt.GetBuilder().CreateMemSet(allocaed, lt.GetBuilder().getInt8(0), *sz, alignment);
}
+
+ return new LLVMSignal(allocaed);
+ }
case Module:
{
Native::Constant *c(0);
@@ 937,6 994,8 @@ namespace K3 {
return new LLVMSignal(b.CreateBitOrPointerCast(*value, b.getInt32Ty()));
} else if (to.IsInt64()) {
return new LLVMSignal(b.CreateBitOrPointerCast(*value, b.getInt64Ty()));
+ } else if (to.IsArrayView()) {
+ return new LLVMSignal(b.CreateIntToPtr(*value, b.getInt8PtrTy()));
}
assert(0 && "unknown native type");
KRONOS_UNREACHABLE;
M src/backends/LLVMModule.cpp +38 -55
@@ 222,9 222,6 @@ namespace K3 {
}
}
- auto connectStub = ir.API(ir.declare<PlumbTy>(Linkage::Export, "Connect"));
- auto disconnectStub = ir.API(ir.declare<PlumbTy>(Linkage::Export, "Disconnect"));
-
auto initStub = ir.API(ir.defn<krt_constructor_call>(Linkage::Export, "Initialize", [&](auto stub, auto args) {
size_t asz(this->GetArgumentType().GetSize()),
rsz(this->GetResultType().GetSize());
@@ 235,7 232,6 @@ namespace K3 {
auto instance = (llvm::Argument*)ai++;
auto self_offset(stub.CreateGEP(instance, stub.CreateCall(sizeOfStateStub, { stub.getInt64(0) }, "sizeof_state")));
- auto plumbingHost = (llvm::Argument*)ai++;
auto argumentData = (llvm::Argument*)ai++;
if (asz) {
@@ 246,7 242,6 @@ namespace K3 {
this->GetArgumentIndex()));
}
- stub.CreateCall(connectStub, { instance, plumbingHost });
stub.CreateCall(initFunc, { self_offset, instance, argumentData, outputBuf }, "init")->setCallingConv(CallingConv::Fast);
stub.CreateRetVoid();
}));
@@ 256,7 251,6 @@ namespace K3 {
auto ai = args.begin();
auto instance = (llvm::Argument*)ai++;
auto host = (llvm::Argument*)ai++;
- stub.CreateCall(disconnectStub, { instance, host });
stub.CreateRetVoid();
}));
@@ 321,21 315,12 @@ namespace K3 {
GlobalVarType::External,
std::make_pair(1, 1),
K3::Type::Nil
- });
+ });
}
}
- auto doNothing = ir.defn<krt_plumbing_callback>(Linkage::Internal, "DoNothing", [&](auto stub, auto args) {
-// typedef void(*krt_plumbing_callback)(krt_host, krt_instance, const struct krt_sym*, void const** slot);
- auto ai = args.begin();
- ai++; ai++; ai++;
- stub.CreateStore(ir.nullConstant<void*>(), ai);
- stub.CreateRetVoid();
- });
-
- doNothing->setCallingConv(CallingConv::C);
-
methods.erase(Type::Pair(Type("unsafe"), Type("accumulator")));
+ int maxNoDefaultSlot = -1;
for (auto& gv : methods) {
std::stringstream sym;
sym << gv.first;
@@ 354,21 339,24 @@ namespace K3 {
auto slotI = globalSymbolTable.find(gv.second.uid);
auto slotIndex = slotI != globalSymbolTable.end() ? std::int32_t(slotI->second) : -1;
- std::int8_t defaultValStatus =
- (gv.second.varType == External &&
- globalKeyTable.find(gv.first) != globalKeyTable.end()) ? 1 : 0;
+ std::int32_t noDefaultVal =
+ ((gv.second.varType == External ||
+ gv.second.varType == Configuration)
+ && globalKeyTable.find(gv.first) != globalKeyTable.end()) ? 1 : 0;
symTableEntry.emplace_back(
ConstantStruct::get(symTy, {
ir.constant(sym.str()),
ir.constant(descr.str()),
- doNothing,
triggerCallback,
- doNothing,
ir.constant(std::int64_t(gv.second.data.GetSize())),
ir.constant(slotIndex),
- ir.constant(defaultValStatus)
- }));
+ ir.constant(noDefaultVal)
+ }));
+
+ if (noDefaultVal && slotIndex > maxNoDefaultSlot) {
+ maxNoDefaultSlot = slotIndex;
+ }
}
}
@@ 379,19 367,44 @@ namespace K3 {
classTy->setBody({
KRT_CLASS_SPEC(COMMA),
ArrayType::get(symTy, symTableEntry.size()),
- }, true);
+ }, true);
#undef COMMA
#undef F
auto symTableTy = ArrayType::get(symTy, symTableEntry.size());
auto symTableInit = llvm::ConstantArray::get(symTableTy, symTableEntry);
+ auto initTableTy = ArrayType::get(ty.ptr, maxNoDefaultSlot + 1);
+ auto initTableInit = llvm::ConstantArray::getNullValue(initTableTy);
+
+ auto slotInitializerData = ir.def(Linkage::Internal, initTableTy, "ExternalInit", false);
+ slotInitializerData->setInitializer(initTableInit);
+
+ ir.implement((llvm::Function*)M->getOrInsertFunction("GetConfigurationSlot", TypeResolver<void*(std::int32_t)>::get(ir)),
+ [&](IRBuilder<>& stub, auto args) {
+ auto ai = args.begin();
+ auto index = (llvm::Argument*)ai++;
+ auto slotPtr = stub.CreateGEP(slotInitializerData, { stub.getInt32(0), index });
+ stub.CreateRet(stub.CreateLoad(slotPtr));
+ });
+
+ auto configureCall = ir.API(ir.defn<krt_configure_call>(Linkage::Export, "SetConfigurationSlot",
+ [&](IRBuilder<>& stub, auto args) {
+ auto ai = args.begin();
+ auto index = (llvm::Argument*)ai++;
+ auto data = (llvm::Argument*)ai++;
+ auto slotPtr = stub.CreateGEP(slotInitializerData, { stub.getInt32(0), index });
+ stub.CreateStore(data, slotPtr);
+ stub.CreateRetVoid();
+ }));
+
std::stringstream evalArg, resultTy;
GetArgumentType().OutputJSONTemplate(evalArg, false);
GetResultType().OutputJSONTemplate(resultTy, false);
auto classInit = ConstantStruct::get(
classTy, {
+ configureCall,
sizeOfStub,
initStub,
getValStub,
@@ 410,36 423,6 @@ namespace K3 {
auto classData = ir.def(Linkage::Export, classTy, "Class", false);
classData->setInitializer(classInit);
- auto makePlumbingFunc = [&](llvm::Function* fn, const char* name, bool onOff) {
- ir.implement(fn, [&](IRBuilder<>& stub, auto args) {
- auto ai = args.begin();
- auto self = (llvm::Argument*)ai++;
- auto env = (llvm::Argument*)ai++;
-
- for (int i = 0; i < symTableEntry.size(); ++i) {
- auto symTable = stub.CreateConstGEP2_32(nullptr, classData, 0, 12);
- auto symStructPtr = stub.CreateConstGEP2_32(nullptr, symTable, 0, i);
- auto symStruct = stub.CreateLoad(symStructPtr);
- auto plumbCall = stub.CreateExtractValue(symStruct, { onOff ? 2u : 4u }, name);
- auto slotIdx = stub.CreateExtractValue(symStruct, { 6 }, "idx");
-
- auto offset = stub.CreateCall(sizeOfStateStub, { stub.CreateZExt(slotIdx, ty.i64) });
- auto slotPtr =
- stub.CreateSelect(stub.CreateICmpSLT(slotIdx, ir.nullConstant<int32_t>()),
- ir.nullConstant<void**>(),
- stub.CreateBitCast(stub.CreateGEP(self, offset), stub.getInt8PtrTy()->getPointerTo()));
-
- auto callInstr = stub.CreateCall(plumbCall, { env, self, symStructPtr, slotPtr });
- callInstr->setCallingConv(CallingConv::C);
- }
-
- stub.CreateRetVoid();
- });
- };
-
- makePlumbingFunc(connectStub, "Connect", true);
- makePlumbingFunc(disconnectStub, "Disconnect", false);
-
GetModule()->getFunction("__launch")->removeFromParent();
#ifndef NDEBUG
std::string errstr;
M src/backends/LLVMSignal.h +4 -4
@@ 9,7 9,7 @@ namespace llvm{
namespace K3 {
namespace Nodes{
- class Monad;
+ class Deps;
};
namespace Backends{
@@ 23,9 23,9 @@ namespace K3 {
Ref<LLVMSignal> Reference();
Ref<LLVMSignal> Dereference(llvm::Value *dereferencedValue);
operator llvm::Value*() {return val;}
- operator const llvm::Value*() const {return val;}
-#ifndef NDEBUG
- int offsetCounter = 0;
+ operator const llvm::Value*() const {return val;}
+#ifndef NDEBUG
+ int offsetCounter = 0;
#endif
};
};
M src/backends/SideEffectCompiler.cpp +559 -211
@@ 24,13 24,109 @@
#include <sstream>
#endif
+#define NI64(op,a,b) Nodes::Native::MakeInt64(#op, Native::op, a, b)
+#define NI32(op,a,b) Nodes::Native::MakeInt32(#op, Native::op, a, b)
+#define FI32(op,a,b) Nodes::Native::MakeFloat(#op, Native::op, a, b)
+
+#define INSTRUMENT_FUNCTIONS 0
+
+#if INSTRUMENT_FUNCTIONS
+template <typename T> void Consume(std::ostream& to, const void*& data) {
+ to << *(T*)data;
+ data = (const char*)data + sizeof(T);
+}
+
+const char* ToStream(std::ostream& os, const char* typeInfo, const void*& dataBlob) {
+ if (dataBlob) {
+ for (;;) {
+ switch (char c = *typeInfo++) {
+ case '\0': return typeInfo;
+ case '%':
+ c = *typeInfo++;
+ switch (c) {
+ case 'f': Consume<float>(os, dataBlob); break;
+ case 'd': Consume<double>(os, dataBlob); break;
+ case 'i': Consume<std::int32_t>(os, dataBlob); break;
+ case 'q': Consume<std::int64_t>(os, dataBlob); break;
+ case '[': {
+ char *loopPoint;
+ for (auto loopCount = strtoull(typeInfo, &loopPoint, 10); loopCount; --loopCount)
+ typeInfo = ToStream(os, loopPoint + 1, dataBlob);
+ break;
+ }
+ case ']': return typeInfo;
+ case '%': os.put('%'); break;
+ default:
+ assert(0 && "Bad format string");
+ }
+ break;
+ default:
+ os.put(c);
+ break;
+ }
+ }
+ } else {
+ for (;;) {
+ switch (char c = *typeInfo++) {
+ case '\0': return typeInfo;
+ case '%':
+ c = *typeInfo++;
+ switch (c) {
+ case 'f': os << "\"Float\""; break;
+ case 'd': os << "\"Double\""; break;
+ case 'i': os << "\"Int32\""; break;
+ case 'q': os << "\"Int64\""; break;
+ case '[': {
+ char *loopPoint;
+ for (auto loopCount = strtoull(typeInfo, &loopPoint, 10); loopCount; --loopCount)
+ typeInfo = ToStream(os, loopPoint + 1, dataBlob);
+ }
+ case ']': break;
+ case '%': os.put('%'); break;
+
+ default:
+ assert(0 && "Bad format string");
+ }
+ break;
+ default:
+ os.put(c);
+ break;
+ }
+ }
+ }
+ return typeInfo;
+}
+KRONOS_ABI_EXPORT int32_t kvm_label(const char *l) {
+ std::clog << "\n\n[" << l << "]\n";
+ return 0;
+}
+KRONOS_ABI_EXPORT int32_t kvm_instrument(int32_t chain, const char *l, const void* data, const char* fmt) {
+ std::clog << l << " : "; ToStream(std::clog, fmt, data);
+ std::clog << "\n";
+ return chain;
+}
+#endif
+
namespace K3
{
+ static CTRef Canonicalize(CTRef data, CRRef r, const Type& e, bool referenced, bool mustCopy, Backends::SideEffectTransform& sfx);
+
+ static bool CheckForArgInputs(CTRef dst) {
+ return Qxx::FromGraph(dst).OfType<SubroutineArgument>().Where(
+ [](auto sa) {
+ if (sa->IsSelf()) return false;
+ if (sa->IsLocalState()) return false;
+ if (sa->IsState()) return false;
+ if (sa->IsOutput()) return false;
+ return true;
+ }).Any();
+ }
+
#pragma region side effect transform infrastructure
namespace Backends
{
static bool IsPair(CTRef graph) {
- const Monad *m;
+ const Deps *m;
if (graph->Cast(m)) return IsPair(m->GetUp(0));
const DataSource *ds;
if (graph->Cast(ds)) return ds->HasPairLayout();
@@ 38,7 134,7 @@ namespace K3
}
static bool IsReference(CTRef graph) {
- const Monad *m;
+ const Deps *m;
if (graph->Cast(m)) return IsReference(m->GetUp(0));
const DataSource *ds;
if (graph->Cast(ds)) return ds->IsReference();
@@ 46,24 142,24 @@ namespace K3
}
static CTRef DereferenceOnce(CTRef graph) {
- //const Monad *m;
- //if (graph->Cast(m)) return Monad::Transfer(DereferenceOnce(m->GetUp(0)),m);
+ //const Deps *m;
+ //if (graph->Cast(m)) return Deps::Transfer(DereferenceOnce(m->GetUp(0)),m);
const DataSource *ds;
if (graph->Cast(ds) && ds->IsReference()) return ds->Dereference();
else return graph;
}
static CTRef DereferenceAll(CTRef graph) {
- //const Monad *m;
- //if (graph->Cast(m)) return Monad::Transfer(DereferenceAll(m->GetUp(0)),m);
+ //const Deps *m;
+ //if (graph->Cast(m)) return Deps::Transfer(DereferenceAll(m->GetUp(0)),m);
const DataSource *ds;
if (graph->Cast(ds) && ds->IsReference()) return DereferenceAll(ds->Dereference());
else return graph;
}
static CTRef SplitFirst(CTRef graph) {
- const Monad *m;
- if (graph->Cast(m)) return Monad::Transfer(SplitFirst(m->GetUp(0)), m);
+ const Deps *m;
+ if (graph->Cast(m)) return Deps::Transfer(SplitFirst(m->GetUp(0)), m);
const DataSource *ds;
if (graph->Cast(ds)) return ds->First();
@@ 71,8 167,8 @@ namespace K3
}
static CTRef SplitRest(CTRef graph) {
- const Monad *m;
- if (graph->Cast(m)) return Monad::Transfer(SplitRest(m->GetUp(0)), m);
+ const Deps *m;
+ if (graph->Cast(m)) return Deps::Transfer(SplitRest(m->GetUp(0)), m);
const DataSource *ds;
if (graph->Cast(ds)) return ds->Rest();
@@ 113,8 209,8 @@ namespace K3
}
static CTRef GetAccessor(CTRef graph) {
- const Monad *m;
- if (graph->Cast(m)) return Monad::Transfer(GetAccessor(m->GetUp(0)), m);
+ const Deps *m;
+ if (graph->Cast(m)) return Deps::Transfer(GetAccessor(m->GetUp(0)), m);
const DataSource *ds;
if (graph->Cast(ds)) return ds->GetAccessor();
@@ 123,7 219,7 @@ namespace K3
static CTRef ComputeSize(CTRef node) {
const Pair* p;
- if (node->Cast(p)) return Native::MakeInt64("uadd", Native::Add, ComputeSize(p->GetUp(0)), ComputeSize(p->GetUp(1)));
+ if (node->Cast(p)) return NI64(Add, ComputeSize(p->GetUp(0)), ComputeSize(p->GetUp(1)));
const IFixedResultType *fr;
if (node->Cast(fr)) return Native::Constant::New(int64_t(fr->FixedResult().GetSize()));
@@ 134,11 230,15 @@ namespace K3
const DataSource *ds;
if (node->Cast(ds)) return ds->SizeOf();
- const Monad *m;
+ const Deps *m;
if (node->Cast(m)) return ComputeSize(m->GetUp(0));
const VariantTuple *vt;
- if (node->Cast(vt)) return Native::MakeInt64("_mul",Native::Mul, vt->GetUp(1), ComputeSize(vt->GetUp(0)));
+ if (node->Cast(vt)) {
+ return NI64(Add,
+ NI64(Mul, vt->GetUp(1), ComputeSize(vt->GetUp(0))),
+ ComputeSize(vt->GetUp(2)));
+ }
const Boundary *b;
if (node->Cast(b)) return ComputeSize(b->GetUp(0));
@@ 160,7 260,7 @@ namespace K3
if (auto ds = out->Cast<DataSource>()) {
return ValidateSfxOutput(ds->GetAccessor());
}
-/* if (auto proc = out->Cast<Monad>()) {
+/* if (auto proc = out->Cast<Deps>()) {
return ValidateSfxOutput(proc->GetUp(0));
}*/
for (auto &u : out->Upstream()) {
@@ 176,17 276,71 @@ namespace K3
return result;
}
- void SideEffectTransform::CompileSubroutineAsync(Subroutine* subr, CTRef sourceBody, CTRef args, CTRef results, bool wait) {
+ #if INSTRUMENT_FUNCTIONS
+ static CTRef InstrumentLabel(CTRef chain, const char *l) {
+ auto diags = Native::ForeignFunction::New("int32", "kvm_label");
+ diags->AddParameter("int32_t", chain, Type::Int32);
+ diags->AddParameter("const char*", CStringLiteral::New(Type(l)), Type(l));
+ return diags;
+ }
+
+ static CTRef InstrumentData(SideEffectTransform& sfx, const char* label, const Type& ty, CTRef data, CTRef chain) {
+ if (IsPair(data)) {
+ return InstrumentData(sfx, label, ty.Rest(), SplitRest(data),
+ InstrumentData(sfx, label, ty.First(), SplitFirst(data), chain));
+ } else {
+ auto diags = Native::ForeignFunction::New("int32", "kvm_instrument");
+ diags->AddParameter("int32", chain, Type::Int32);
+ diags->AddParameter("const char*", CStringLiteral::New(Type(label)), Type(label));
+
+ if (ty.GetSize()) {
+ data = Canonicalize(data, data->GetReactivity(), ty, true, false, sfx);
+ } else {
+ data = CStringLiteral::New(Type("()"));
+ }
+
+ diags->AddParameter("const void*", GetAccessor(data), ty);
+
+ std::stringstream tyS;
+ ty.OutputFormatString(tyS);
+
+ tyS << " (";
+
+ std::stringstream dataBundle;
+ dataBundle << "(" << *data << ")";
+
+ for (auto c : dataBundle.str()) {
+ switch (c) {
+ case '\n': break;
+ case '%': tyS << "%%"; break;
+ default: tyS.put(c); break;
+ }
+ }
+
+ tyS << ")";
+
+
+ Type tyStr(tyS.str().c_str());
+ diags->AddParameter("const char*", CStringLiteral::New(tyStr), tyStr);
+ return diags;
+ }
+ }
+ #endif
+
+ void SideEffectTransform::CompileSubroutineAsync(const char* label, const Type& arg, const Type& res, Subroutine* subr, CTRef sourceBody, CTRef args, CTRef results, bool wait) {
+ assert(!CheckForArgInputs(results));
+
TLS::WithNewStack([&]() mutable {
#ifndef NDEBUG
if (TLS::GetCurrentInstance()->ShouldTrace("Compile", subr->GetLabel())) {
std::clog << "Compile: [" << subr->GetLabel() << "]\n" << *sourceBody << "\n\nArgs: " << *args << "\nResults: " << *results ;
}
#endif
- subr->SetBody(Compile(symbols, sourceBody, args, results));
+ auto body = Compile(symbols, sourceBody, args, results, label, arg, res);
+ subr->SetBody(body);
return 0;
});
- Monad *m;
+ Deps *m;
SubroutineMeta *sm;
if (subr->GetBody()->Cast(m) && m->GetUp(m->GetNumCons()-1)->Cast(sm)) {
if (sm->HasLocalState) AllocatesState();
@@ 257,9 411,9 @@ namespace K3
auto h1 = (*this)(node->GetUp(0)) + (int)o;
auto h2 = (*this)(node->GetUp(1));
return h1 | h2;
- }
+ }
- if (IS_A(Monad, AtIndex, Reference, BoundaryBuffer)) {
+ if (IS_A(Deps, AtIndex, Reference, BoundaryBuffer, BitCast)) {
// these nodes may pass undereferenced pointers from up to downstream
if (node->GetNumCons() == 0) return false;
for (unsigned i(1); i < node->GetNumCons(); ++i) (*this)(node->GetUp(i));
@@ 312,13 466,13 @@ namespace K3
};
CTRef SideEffectTransform::Process(CTRef body, const Reactive::Node *rootReactivity) {
- CTRef processed = Monad::New(CopyData(results, (*this)(body), rootReactivity, true, false, false));
+ CTRef processed = Deps::New(CopyData(results, (*this)(body), rootReactivity, true, false, false));
struct HazardousEffect {
CTRef ReadPointer;
CTRef Pure;
CTRef Effect;
- Monad *Guard;
+ Deps *Guard;
std::int64_t size;
};
std::vector<HazardousEffect> protectForHazards;
@@ 335,7 489,7 @@ namespace K3
if (fx.WriteValue == nullptr) {
// this side effect releases the allocation
- hfx.Guard = Monad::New();
+ hfx.Guard = Deps::New();
hfx.Guard->Connect(fx.WritePointer);
hfx.Effect = ReleaseBuffer::New(hfx.Guard, fx.ReadPointer->GetUp(0));
protectForHazards.emplace_back(hfx);
@@ 349,7 503,7 @@ namespace K3
HazardousEffect write = hfx;
write.Effect = cpy;
write.Pure = cpy->GetUp(1);
- write.Guard = Monad::New();
+ write.Guard = Deps::New();
write.Guard->Connect(cpy->GetUp(0));
cpy->Reconnect(0, write.Guard);
protectForHazards.emplace_back(write);
@@ 366,7 520,7 @@ namespace K3
SetStatePointer(recursiveBranch);
}
- auto complete = Monad::New();
+ auto complete = Deps::New();
complete->Connect(GetStatePointer());
complete->Connect(processed);
@@ 418,7 572,7 @@ namespace K3
}
CTRef SideEffectTransform::GetDataLayout(CTRef graph) {
- Monad *m;
+ Deps *m;
if (graph->Cast(m)) return GetDataLayout(m->GetUp(0));
const DataSource *ds;
@@ 430,8 584,8 @@ namespace K3
}
CTRef SideEffectTransform::GetDataAccessor(CTRef graph) {
- Monad *m;
- if (graph->Cast(m)) return Monad::Transfer(GetDataAccessor(m->GetUp(0)), m);
+ Deps *m;
+ if (graph->Cast(m)) return Deps::Transfer(GetDataAccessor(m->GetUp(0)), m);
const DataSource *ds;
if (graph->Cast(ds)) return ds->GetAccessor();
@@ 439,8 593,8 @@ namespace K3
}
CTRef SideEffectTransform::GetDereferencedAccessor(CTRef graph) {
- Monad *m;
- if (graph->Cast(m)) return Monad::Transfer(GetDereferencedAccessor(m->GetUp(0)), m);
+ Deps *m;
+ if (graph->Cast(m)) return Deps::Transfer(GetDereferencedAccessor(m->GetUp(0)), m);
const DataSource *ds;
if (graph->Cast(ds)) {
@@ 449,12 603,12 @@ namespace K3
} else return graph;
}
- static CTRef TransferDependencies(CTRef src, bool deref, Monad*& deps) {
+ static CTRef TransferDependencies(CTRef src, bool deref, Deps*& deps) {
if (deref) src = DereferenceAll(src);
- Monad *m;
+ Deps *m;
if (src->Cast(m)) {
- if (deps == nullptr) deps = Monad::New( );
+ if (deps == nullptr) deps = Deps::New( );
for (unsigned i(0); i < m->GetNumCons(); ++i)
deps->Connect(m->GetUp(i));
@@ 495,7 649,9 @@ namespace K3
}
CTRef SideEffectTransform::CopyData(CTRef dst, CTRef src, CRRef reactivity, bool byVal, bool mutatesState, bool doesInit) {
- Monad *deps(nullptr);
+ Deps *deps(nullptr);
+
+ assert(!CheckForArgInputs(dst));
dst = TransferDependencies(dst, byVal, deps);
src = TransferDependencies(src, byVal, deps);
@@ 505,7 661,7 @@ namespace K3
bool dstIsPair = IsPair(dst), srcIsPair = IsPair(src);
if (dstIsPair || srcIsPair || !IsFused(reactivity)) {
- return Monad::New(CopyData(SplitFirst(dst), SplitFirst(src), reactivity ? reactivity->First() : 0, byVal, mutatesState,doesInit),
+ return Deps::New(CopyData(SplitFirst(dst), SplitFirst(src), reactivity ? reactivity->First() : 0, byVal, mutatesState,doesInit),
CopyData(SplitRest(dst), SplitRest(src), reactivity ? reactivity->Rest() : 0, byVal, mutatesState,doesInit));
}
@@ 522,7 678,7 @@ namespace K3
finalSz = dst_ds->SizeOf();
finalMode = Copy::MemCpy;
} else if (Typed::IsNil(src)) {
- return deps ? Monad::Transfer(Typed::Nil(), deps) : src;
+ return deps ? Deps::Transfer(Typed::Nil(), deps) : src;
} else {
ResultTypeWithNoArgument tmp(src);
@@ 532,24 688,24 @@ namespace K3
finalMode = Copy::Store;
}
- /* flatten out any monads inside data sources */
+ /* flatten out any Depss inside data sources */
finalSrc = TransferDependencies(finalSrc, false, deps);
finalDst = TransferDependencies(finalDst, false, deps);
/* elided copy or null destination */
if (*finalDst == *finalSrc || Typed::IsNil(dst_ds->GetAccessor())) {
- if (deps) return Monad::Transfer(Typed::Nil(), deps);
+ if (deps) return Deps::Transfer(Typed::Nil(), deps);
else return Typed::Nil();
}
CTRef result(0);
- if (deps) finalDst = Monad::Transfer(finalDst, deps);
+ if (deps) finalDst = Deps::Transfer(finalDst, deps);
assert(reactivity == nullptr || reactivity->IsFused());
result = Copy::New(finalDst, finalSrc, finalSz, finalMode, reactivity, 1, mutatesState, doesInit);
return result;
} else if (Typed::IsNil(dst)) {
- if (deps) return Monad::Transfer(dst, deps);
+ if (deps) return Deps::Transfer(dst, deps);
else return dst;
} else {
INTERNAL_ERROR("Bad copy operation");
@@ 558,7 714,7 @@ namespace K3
bool GraphvizReduceProcEdgeWeight(std::ostream& dot, CTRef d, CTRef u) {
// reduce layout weight of procedural data-less flows
- if (IsOfExactType<Monad>(d) || IsOfExactType<Monad>(u)) {
+ if (IsOfExactType<Deps>(d) || IsOfExactType<Deps>(u)) {
if (d->GetNumCons() && d->GetUp(0) == u) return false;
dot << "n" << u << " -> n" << d << " [weight=0.2, style=dashed, color=gray];\n";
return true;
@@ 587,11 743,11 @@ namespace K3
SubroutineArgument *arg;
if (n->Cast(arg)) {
- dot << "n" << n << " [label=\"arg" << arg->GetID() << ":" << arg->FixedResult() << "\"];\n";
+ dot << "n" << n << " [label=\"arg" << arg->GetID() << "\"];\n";
return true;
}
- if (IsOfExactType<Monad>(n)) {
+ if (IsOfExactType<Deps>(n)) {
dot << "n" << n << " [label=\"Depends\"];\n";
return true;
}
@@ 599,7 755,7 @@ namespace K3
return false;
}
- Graph<Typed> SideEffectTransform::Compile(IInstanceSymbolTable& symbols, const CTRef pureBody, const CTRef arguments, const CTRef results) {
+ Graph<Typed> SideEffectTransform::Compile(IInstanceSymbolTable& symbols, const CTRef pureBody, const CTRef arguments, const CTRef results, const char *l, const Type& argTy, const Type& resTy) {
auto result = Graph<Typed>{};
if (symbols.GetMemoized(std::make_tuple(pureBody, arguments, results), result)) {
return result;
@@ 670,14 826,30 @@ namespace K3
symbols.SetMemoized(std::make_tuple(pureBody, arguments, results), finalBody);
//ExportGraphviz(std::clog, "sfx", finalBody, GraphvizReduceOffsets, GraphvizReduceProcEdgeWeight);
+ #if INSTRUMENT_FUNCTIONS
+ if (l) {
+ Deps* d = nullptr;
+ finalBody->Cast(d);
+ auto meta = d->GetUp(d->GetNumCons() - 1);
+ d->Reconnect(d->GetNumCons() - 1,
+ InstrumentData(sfx, "->", resTy, results,
+ InstrumentData(sfx, "<-", argTy, arguments,
+ InstrumentLabel(
+ Deps::New(Native::Constant::New((int32_t)0), d->GetUp(0)), l))));
+ d->Connect(meta);
+ }
+ #endif
+
return finalBody;
}
}
Graph<Typed> SideEffectTransform::Compile(IInstanceSymbolTable& symbols, CTRef body, const Type& arg, const Type& res) {
- return Compile(symbols, body,
+ auto cmp = Compile(symbols, body,
DataSource::New(SubroutineArgument::In(1,4), Reference::New(Native::Constant::New(arg, 0))),
- DataSource::New(SubroutineArgument::Out(2,4), Reference::New(Native::Constant::New(res, 0))));
+ DataSource::New(SubroutineArgument::Out(2,4), Reference::New(Native::Constant::New(res, 0))), "root", arg, res);
+
+ return cmp;
}
K3::TypeDescriptor pointerTag("Ptr");
@@ 703,7 875,7 @@ namespace K3
if (node->Cast(ref)) return NeverHasData(ref->GetUp(0));
const Dereference *deref;
if (node->Cast(deref)) return NeverHasData(deref->GetUp(0));
- const Monad* m;
+ const Deps* m;
if (node->Cast(m)) return NeverHasData(m->GetUp(0));
const Offset* ofs;
if (node->Cast(ofs)) return NeverHasData(m->GetUp(0));
@@ 736,7 908,7 @@ namespace K3
const DataSource* ds;
if (node->Cast(ds)) return ReduceType(ds->GetDataLayout());
- const Monad *m;
+ const Deps *m;
if (node->Cast(m)) return ReduceType(m->GetUp(0));
const BoundaryBuffer* b;
@@ 785,6 957,7 @@ namespace K3
default:
strm << (isOutput ? "%out" : "%in") << ID - 1;
}
+ strm << "<" << type << ">";
}
unsigned SubroutineArgument::ComputeLocalHash() const {
@@ 842,9 1015,9 @@ namespace K3
}
CTRef Reference::New(CTRef upstream) {
- /* maintain Monadic dependencies */
- Monad *m;
- if (upstream->Cast(m)) return Monad::Transfer(New(upstream->GetUp(0)), m);
+ /* maintain Depsic dependencies */
+ Deps *m;
+ if (upstream->Cast(m)) return Deps::Transfer(New(upstream->GetUp(0)), m);
/* simplify */
Dereference *dr;
@@ 853,15 1026,15 @@ namespace K3
}
CTRef Offset::New(CTRef buffer, CTRef offset) {
- /* maintain Monadic dependencies */
+ /* maintain Depsic dependencies */
Native::Constant *constOffset;
if (offset->Cast(constOffset)) {
if (constOffset->FixedResult() == Type::Int64 && *(int64_t*)constOffset->GetPointer() == 0) {
return buffer;
}
}
- Monad *m;
- if (buffer->Cast(m)) return Monad::Transfer(New(m->GetUp(0), offset), m);
+ Deps *m;
+ if (buffer->Cast(m)) return Deps::Transfer(New(m->GetUp(0), offset), m);
else return new Offset(buffer, offset);
}
@@ 925,7 1098,7 @@ namespace K3
auto a(GetAccessor());
do {
if (IsOfExactType<Nodes::Dereference>(a)) return true;
- } while (IsOfExactType<Monad>(a) && (a = a->GetUp(0)));
+ } while (IsOfExactType<Deps>(a) && (a = a->GetUp(0)));
return false;
}
@@ 991,7 1164,7 @@ namespace K3
auto buf(Buffer::New(sfx, match->SizeOf(), Buffer::Stack, 16));
auto buf_ds(DataSource::New(buf, match->Reference()->GetDataLayout()));
return DataSource::New(
- Monad::New(buf_ds->Dereference()->GetAccessor(), sfx.CopyData(buf_ds, this, r, true, false, false)),
+ Deps::New(buf_ds->Dereference()->GetAccessor(), sfx.CopyData(buf_ds, this, r, true, false, false)),
match->GetDataLayout());
}
@@ 1003,7 1176,7 @@ namespace K3
}
CTRef VariantTuple::GraphRest() const {
- return VariantTuple::New(GetUp(0), Native::MakeInt64("_sub", Native::Sub, GetUp(1), Native::Constant::New(int64_t(1))), GetUp(2), GetRecurrenceDelta());
+ return VariantTuple::New(GetUp(0), NI64(Sub, GetUp(1), Native::Constant::New(int64_t(1))), GetUp(2), GetRecurrenceDelta());
}
Buffer* Buffer::ConstructShallowCopy() const {
@@ 1052,30 1225,30 @@ namespace K3
strm << "Buffer" << GUID;
}
- CTRef Monad::GraphFirst() const {
+ CTRef Deps::GraphFirst() const {
return Transfer(First::New(GetUp(0)), this);
//New(First::New(GetUp(0)),this);
}
- CTRef Monad::GraphRest() const {
+ CTRef Deps::GraphRest() const {
return Transfer(Rest::New(GetUp(0)), this);
// return New(Rest::New(GetUp(0)),this);
}
- CTRef Monad::IdentityTransform(GraphTransform<const Typed, CTRef>& state) const {
+ CTRef Deps::IdentityTransform(GraphTransform<const Typed, CTRef>& state) const {
if (GetNumCons() == 1) return state(GetUp(0));
else return TypedPolyadic::IdentityTransform(state);
}
- CTRef Monad::Transfer(CTRef upstream, const Monad* deps) {
+ CTRef Deps::Transfer(CTRef upstream, const Deps* deps) {
DataSource *ds;
if (upstream->Cast(ds)) {
return DataSource::New(Transfer(ds->GetAccessor(), deps), ds->GetDataLayout());
}
- Monad *m(New());
+ Deps *m(New());
m->Connect(upstream);
if (deps->isDataProtector) {
- /* must maintain this monad intact because its identity (via pointer) matters */
+ /* must maintain this Deps intact because its identity (via pointer) matters */
m->Connect(deps);
} else {
for (unsigned i(1); i < deps->GetNumCons(); ++i) m->Connect(deps->GetUp(i));
@@ 1083,14 1256,14 @@ namespace K3
return m;
}
- void Monad::Connect(CTRef dependency) {
+ void Deps::Connect(CTRef dependency) {
if (GetNumCons() == 0) SetReactivity(dependency->GetReactivity());
DataSource *ds;
- Monad *m;
+ Deps *m;
Pair *p;
Invariant::Constant *ic;
if (dependency->Cast(m) && m->isDataProtector == false) {
- /* flatten chained Monads that are not data protectors */
+ /* flatten chained Depss that are not data protectors */
for (auto up : m->Upstream()) {
if (Typed::Nil() != (up)) Connect(up);
}
@@ 1107,9 1280,12 @@ namespace K3
}
}
- CTRef SubroutineArgument::In(size_t ID, CTRef graph, const char *l) {
- Monad *m;
- if (graph->Cast(m)) return In(ID, m->GetUp(0), l);
+ CTRef SubroutineArgument::New(bool isInput, size_t ID, CTRef graph, const char *l) {
+ if (l == nullptr) {
+ l = isInput ? "in" : "out";
+ }
+ Deps *m;
+ if (graph->Cast(m)) return New(isInput, ID, m->GetUp(0), l);
const DataSource *ds;
if (graph->Cast(ds)) {
@@ 1118,11 1294,20 @@ namespace K3
int align = 0;
IAlignmentTrackerNode *at;
if (ds->GetAccessor()->Cast(at)) align = at->GetAlignment();
- return In(ID, align, l);
+ if (isInput) {
+ return In(ID, align, l);
+ } else {
+ return Out(ID, align, l);
+ }
}
}
ResultTypeWithNoArgument rtnoa(graph);
- return In(ID, graph->Result(rtnoa), l);
+ auto t = graph->Result(rtnoa);
+ if (isInput) {
+ return In(ID, t, l);
+ } else {
+ return Out(ID, t, l);
+ }
}
#pragma endregion
@@ 1141,10 1326,10 @@ namespace K3
return IdentityTransform(sfx);
}
- CTRef Monad::SideEffects(SideEffectTransform& sfx) const {
- Monad *side(Monad::New());
+ CTRef Deps::SideEffects(SideEffectTransform& sfx) const {
+ Deps *side(Deps::New());
for (unsigned i(1); i < GetNumCons(); ++i) side->Connect(GetAccessor(sfx(GetUp(i))));
- if (GetNumCons()) return Monad::New(sfx(GetUp(0)), side);
+ if (GetNumCons()) return Deps::New(sfx(GetUp(0)), side);
else return side;
}
@@ 1164,7 1349,7 @@ namespace K3
auto ptr = GetSlot::New(sfx.GetSymbolTable().GetIndex(uid));
/*Offset::New(SubroutineArgument::Self(),
- Native::MakeInt64("umul", Native::Mul,
+ NI64(Mul,
Native::Constant::New(int64_t(sfx.GetSymbolTable().GetIndex(uid))),
SizeOfPointer::New()));*/
@@ 1178,7 1363,7 @@ namespace K3
const DataSource* ptr_ds = DataSource::New(ptr, Reference::New(ReduceType(GetUp(0))));
const DataSource* new_ds;
- const Monad* new_m;
+ const Deps* new_m;
if (new_val->Cast(new_m) && new_m->GetUp(0)->Cast(new_ds)) {
auto tmp1(ptr_ds), tmp2(new_ds);
while (tmp1->IsReference()) tmp1 = tmp1->Dereference();
@@ 1187,32 1372,40 @@ namespace K3
//return sfx.CopyData(ptr_ds->Dereference(),tmp2->Reference(),0,false);
return Copy::New(ptr_ds->GetAccessor(),
tmp2->Reference()->Reference()->GetAccessor(),
- Monad::Transfer(SizeOfPointer::New(), new_m), Copy::Store, new_val->GetReactivity(), 1, true, false);
+ Deps::Transfer(SizeOfPointer::New(), new_m), Copy::Store, new_val->GetReactivity(), 1, true, false);
}
}
auto buf(Buffer::New(sfx, ptr_ds->Dereference()->Dereference()->SizeOf(), Buffer::Stack, 16));
const DataSource* buf_ds = DataSource::New(buf, ptr_ds->Dereference()->GetDataLayout());
- return Monad::New(Copy::New(ptr_ds->GetAccessor(), Reference::New(buf), SizeOfPointer::New(), Copy::Store, 0, 1, true, false),
+ return Deps::New(Copy::New(ptr_ds->GetAccessor(), Reference::New(buf), SizeOfPointer::New(), Copy::Store, 0, 1, true, false),
sfx.CopyData(buf_ds, new_val, 0, true, true, false));
}
CTRef GetGlobalVariable::SideEffects(SideEffectTransform& sfx) const {
- CTRef initializer = nullptr;
+ CTRef initializer = nullptr;;
auto layout(Reference::New(Native::Constant::New(t, 0)));
+ auto slotIndex = sfx.GetSymbolTable().GetIndex(uid);
+
if (GetNumCons()) {
+ initializer = sfx(GetUp(0));
+ } else if (IsConfigurationSlot()) {
+ initializer = DataSource::New(Configuration::New(t, slotIndex), layout);
+ }
+
+ if (initializer) {
/* this variable has an initializer */
auto buf = Buffer::New(sfx, Native::Constant::New(int64_t(t.GetSize())), Buffer::Module, 16);
- initializer = Monad::New(buf, sfx.CopyData(DataSource::New(buf, layout), sfx(GetUp(0)), sfx.GetSymbolTable().GetInitializerReactivity(), true, true, true));
+ initializer = Deps::New(buf, sfx.CopyData(DataSource::New(buf, layout), initializer,
+ sfx.GetSymbolTable().GetInitializerReactivity(), true, true, true));
+ }
+
+ if (key.IsNil() == false) {
+ sfx.GetSymbolTable().RegisterExternalVariable(key, t, uid, k, vectorRate, clock);
}
- Typed* ptr = GetSlot::New(sfx.GetSymbolTable().GetIndex(uid), initializer);
-
- if (key.IsNil() == false)
- sfx.GetSymbolTable().RegisterExternalVariable(key, t, uid, k, vectorRate, clock);
-
- return DataSource::New(ptr, layout);
+ return DataSource::New(GetSlot::New(slotIndex, initializer), layout);
}
CTRef ExternalAsset::SideEffects(SideEffectTransform& sfx) const {
@@ 1271,11 1464,11 @@ namespace K3
while (up_ds->IsReference()) up_ds = up_ds->Dereference();
return DataSource::New(
BoundaryBuffer::New(up_ds->Reference()->GetAccessor(),
- Monad::New(bufferPtr, sfx.CopyData(buffer, upstream, up, true, true, true)), up),
+ Deps::New(bufferPtr, sfx.CopyData(buffer, upstream, up, true, true, true)), up),
buffer->GetDataLayout());
} else {
return
- BoundaryBuffer::New(sfx.GetDereferencedAccessor(upstream), Monad::New(sfx.GetDereferencedAccessor(buffer),
+ BoundaryBuffer::New(sfx.GetDereferencedAccessor(upstream), Deps::New(sfx.GetDereferencedAccessor(buffer),
sfx.CopyData(buffer, upstream, up, true, true, true)), up);
}
}
@@ 1349,7 1542,7 @@ namespace K3
auto bufferPtr(sfx.GetStatePointer());
auto buffer(DataSource::New(bufferPtr, Reference::New(Native::Constant::New(FixedResult(),nullptr))));
- CTRef output = Monad::New(buffer);
+ CTRef output = Deps::New(buffer);
sfx.SetStatePointer(Offset::New(bufferPtr, buffer->Dereference()->SizeOf()));
for (unsigned i(0);i < GetNumCons();++i) {
@@ 1359,7 1552,7 @@ namespace K3
if (upstream->Cast(up_ds) && up_ds->IsReference()) {
while (up_ds->IsReference()) up_ds = up_ds->Dereference();
}
- output = Monad::New(output, sfx.CopyData(buffer, upstream, up, true, true, true));
+ output = Deps::New(output, sfx.CopyData(buffer, upstream, up, true, true, true));
}
return output;
}
@@ 1372,25 1565,9 @@ namespace K3
} else return false;
}
- static CTRef Canonicalize(CTRef data, CRRef r, const Type& e, bool referenced, bool mustCopy, SideEffectTransform& sfx) {
- if (mustCopy == false) {
- const DataSource* ds;
- data = DereferenceAll(data);
- if (data->Cast(ds) && ds->HasPairLayout() == false && IsFused(r)) {
- if (referenced) {
- if (ds->CanTakeReference()) return ds->Reference();
- } else return ds;
- }
- }
- auto buf(Buffer::New(sfx,e.GetSize(), Buffer::Stack));
- auto buf_ds(DataSource::New(buf, Reference::New(Native::Constant::New(e, 0))));
- auto val = Monad::New(buf_ds, sfx.CopyData(buf_ds, data, r, true, false, false));
- if (!referenced) return DereferenceOnce(val);
- else return val;
- }
-
namespace Native {
CTRef ForeignFunction::SideEffects(SideEffectTransform& sfx) const {
+
ForeignFunction *ff = ConstructShallowCopy();
if (Symbol.back() == '!') sfx.MutatesGVars();
CTRef returnValue = DataSource::New(Typed::Nil(), Native::Constant::New(Type(false), nullptr));
@@ 1423,7 1600,7 @@ namespace K3
}
return Pair::New(
DataSource::New(ff, Native::Constant::New(ff->ReturnValue, nullptr)),
- Monad::New(returnValue, ff));
+ Deps::New(returnValue, ff));
}
CTRef SelfID::SideEffects(SideEffectTransform& sfx) const {
@@ 1474,38 1651,115 @@ namespace K3
return DataSource::New(tree, layout);
}
- CTRef Memory::SideEffects(SideEffectTransform& sfx) const {
- CTRef bufferPtr = sfx.GetLocalStatePointer();
- CTRef tableSetter = sfx(GetUp(0));
- sfx.SetLocalStatePointer(Offset::New(bufferPtr, Native::Constant::New(int64_t(sz * elTy.GetSize()))));
- CTRef table = DataSource::New(
- bufferPtr,
- Reference::New(Native::Constant::New(Type::Chain(elTy, sz, Type::Nil),nullptr)));
-
- auto react = GetReactivity();
- if (Qxx::FromGraph(react).OfType<Reactive::DriverNode>().Any() == false) {
- react = sfx.GetSymbolTable().GetInitializerReactivity();
+ static void GetSliceBounds(Backends::SideEffectTransform& sfx, int staticLen, const Type& elementType,
+ CRRef rx, CTRef vec, CTRef& ptr, CTRef &offset, CTRef &limit) {
+ if (staticLen < 0) {
+ ptr = BitCast::New(Type::ArrayView(elementType),
+ GetAccessor(DereferenceAll(SplitFirst(vec))));
+ auto ofsl = SplitRest(vec);
+ offset = GetAccessor(DereferenceAll(SplitFirst(ofsl)));
+ limit = GetAccessor(DereferenceAll(SplitRest(ofsl)));
+ } else {
+ auto bufType = Type::List(elementType, staticLen);
+ ptr = GetAccessor(Canonicalize(vec, rx, bufType, true, false, sfx));
+ limit = Native::Constant::New((int32_t)staticLen);
+ offset = Native::Constant::New((int32_t)0);
}
-
- return Monad::New(table, sfx.CopyData(table, tableSetter, react,true,true,true));
}
- CTRef Transaction::SideEffects(SideEffectTransform& sfx) const {
- auto memMonad = GetAccessor(sfx(GetUp(0)))->Cast<Monad>();
- CTRef idx = GetAccessor(DereferenceAll(sfx(GetUp(1))));
+ CTRef SubArray::SideEffects(Backends::SideEffectTransform& sfx) const {
+ CTRef ptr = nullptr, offset = nullptr, limit = nullptr;
+
+ auto vec(sfx(GetUp(0)));
+ auto skip = sfx(GetUp(1));
+ GetSliceBounds(sfx, src.sourceLen, src.GetElementType(), GetReactivity(), vec, ptr, offset, limit);
+
+ skip = NI32(Add, skip, offset);
+ skip = MakeConversionNode<int64_t, Native::ToInt64>(skip, Type::Int32);
+
+ auto zero = Native::Constant::New((int64_t)0);
+ auto skipBelowZero = NI64(Min, zero, skip);
+ auto skipAboveZero = NI64(Max, zero, skip);
+
+ limit = MakeConversionNode<int64_t, Native::ToInt64>(limit, Type::Int32);
+ offset = MakeConversionNode<int64_t, Native::ToInt64>(offset, Type::Int32);
- idx = Native::MakeInt32("_clamp", Native::ClampIndex, idx, Native::Constant::New(int32_t(GetMemory()->GetSize())));
+ auto buf = Buffer::New(sfx, src.GetElementType().GetSize() * sliceLen, Buffer::Allocation::StackZeroed);
+ auto cSz = Native::Constant::New((int64_t)src.GetElementType().GetSize());
+
+ auto size =
+ NI64(Max, zero,
+ NI64(Mul, cSz,
+ NI64(Min,
+ NI64(Add, Native::Constant::New((int64_t)sliceLen), skipBelowZero),
+ NI64(Sub, limit, skipAboveZero))));
+
+ auto cpy =
+ Copy::New(
+ Offset::New(buf,
+ NI64(Mul,
+ skipBelowZero,
+ Native::MakeInt64("neg", Native::Neg, cSz))),
+ Offset::New(GetAccessor(ptr),
+ NI64(Mul, skipAboveZero, cSz)),
+ size, Copy::MemCpy, GetReactivity(), 1, false, true);
+
+ return DataSource::New(
+ Deps::New(buf, cpy),
+ Reference::New(Native::Constant::New(FixedResult(), nullptr)));
+ }
- auto sfxValue = DataSource::New(
- AtIndex::New(Type::Chain(GetMemory()->GetElementType(), GetMemory()->GetSize(), Type()), memMonad, idx),
- Reference::New(Native::Constant::New(GetMemory()->GetElementType(), nullptr)));
+ static CTRef MakeSlice(Backends::SideEffectTransform& sfx, CTRef ptr, CTRef offset, CTRef length, CRRef rx) {
+ auto rawSliceTy = Type::Tuple(Type::Int64, Type::Int32, Type::Int32);
+ auto sliceBuf = Buffer::New(sfx, rawSliceTy, Buffer::Stack);
+
+ auto int64sz = Native::Constant::New((int64_t)Type::Int64.GetSize());
+ auto int32sz = Native::Constant::New((int32_t)Type::Int32.GetSize());
+
+ auto output = Deps::New();
+ auto bufPtr = sliceBuf;
+
+ output->Connect(sliceBuf);
+
+ output->Connect(
+ Copy::New(bufPtr, ptr, int64sz, Copy::Store, rx, 1, false, true));
+ bufPtr = Offset::New(bufPtr, int64sz);
+
+
+ output->Connect(
+ Copy::New(bufPtr, offset, int32sz, Copy::Store, rx, 1, false, true));
+ bufPtr = Offset::New(bufPtr, int32sz);
- sfx.AddSideEffect(sfxValue, GetUp(2), sfxValue, GetReactivity(), GetMemory()->GetElementType().GetSize());
- return sfxValue;
+ output->Connect(
+ Copy::New(bufPtr, length, int32sz, Copy::Store, rx, 1, false, true));
+
+ return DataSource::New(
+ output,
+ Reference::New(Native::Constant::New(rawSliceTy, nullptr)));
+ }
+
+ CTRef Slice::SideEffects(Backends::SideEffectTransform& sfx) const {
+ auto vec = sfx(GetUp(0));
+ auto skip = sfx(GetUp(1));
+ auto take = sfx(GetUp(2));
+
+
+ CTRef limit = nullptr;
+ CTRef offset = nullptr;
+ CTRef ptr = nullptr;
+
+ GetSliceBounds(sfx, src.sourceLen, src.GetElementType(), GetReactivity(), vec, ptr, offset, limit);
+
+ auto skipOffs = NI32(Add, offset, skip);
+ auto length = NI32(Min, take, NI32(Sub, limit, skipOffs));
+
+ return MakeSlice(sfx, BitCast::New(Type::Int64, ptr),
+ skipOffs, length, GetReactivity());
}
CTRef RingBuffer::SideEffects(SideEffectTransform& sfx) const {
CTRef evictPtr, bufferPtr, rover, statePtr(sfx.GetLocalStatePointer());
+ CTRef bufferLen = nullptr;
if (len < 2) {
bufferPtr = evictPtr = statePtr;
rover = Native::Constant::New(int32_t(0));
@@ 1517,79 1771,152 @@ namespace K3
sfx(GetUp(0)), sfx.GetSymbolTable().GetInitializerReactivity(),
true,true,true));
- evictPtr = bufferPtr = Monad::New(bufferPtr, initializer);
+ evictPtr = bufferPtr = Deps::New(bufferPtr, initializer);
} else {
/* generate ring buffer loop */
- auto state(
- DataSource::New(
- statePtr,
- Reference::New(Native::Constant::New(
- Type::Pair(
- Type::Chain(elementType, len, Type::Nil),
- Type::Int32), 0))));
+ bufferPtr = statePtr;
+
+ switch (timeBase) {
+ case smp:
+ bufferLen = Native::Constant::New((int32_t)len);
+ break;
+ case sec:
+ {
+ auto clockSig = Qxx::FromGraph(GetReactivity())
+ .OfType<Reactive::DriverNode>()
+ .SelectMember(&Reactive::DriverNode::GetID)
+ .FirstOrDefault(Type::Nil);
+
+ if (clockSig.IsNil()) {
+ bufferLen = Native::Constant::New((int32_t)1);
+ } else {
+ DriverSignature dsig(clockSig);
+ auto rateSig = Type::User(&ReactiveRateTag, dsig.GetMetadata());
+ auto rateKey = TLS::GetCurrentInstance()->Memoize(rateSig);
+ auto rateSlot = sfx.GetSymbolTable().GetIndex(rateKey);
+
+ sfx.GetSymbolTable()
+ .RegisterExternalVariable(rateSig, Type::Float32, rateKey, GlobalVarType::Configuration,
+ { 1,1 }, Type::Nil);
+
+ bufferLen =
+ MakeConversionNode<int32_t, Native::ToInt32>(
+ Dereference::New(Configuration::New(Type::Float32, rateSlot), Type::Float32),
+ Type::Float32);
+
+ bufferLen =
+ MakeConversionNode<int64_t, Native::ToInt64>(
+ bufferLen, Type::Int32);
- sfx.SetLocalStatePointer(
- Offset::New(statePtr,
- Native::Constant::New(int64_t(len * elementType.GetSize() + Type::Int32.GetSize()))));
+ bufferLen = NI64(Mul,
+ bufferLen,
+ Native::Constant::New((int64_t)len));
+
+ bufferLen = NI64(BitShiftRight,
+ bufferLen,
+ Native::Constant::New((int64_t)20));
+
+ bufferLen = MakeConversionNode<int32_t, Native::ToInt32>(
+ bufferLen, Type::Int64);
+
+ bufferLen =
+ NI32(Add, Native::Constant::New((int32_t)1),
+ bufferLen);
- auto indexDs(state->Rest( ));
+ auto lenPtr = bufferPtr;
+ auto int32sz = Native::Constant::New((int64_t)Type::Int32.GetSize());
+ bufferPtr = Offset::New(bufferPtr, int32sz);
- auto initIndex = Copy::New(indexDs->GetAccessor( ), Native::Constant::New(int32_t(0 - elementType.GetSize( ))),
+ bufferLen = Dereference::New(
+ Copy::New(lenPtr, bufferLen, int32sz,
+ Copy::Store, sfx.GetSymbolTable().GetInitializerReactivity(),
+ 1, false, true),
+ Type::Int32);
+ }
+ break;
+ }
+ }
+
+ auto elSz = Native::Constant::New((int32_t)elementType.GetSize());
+ auto bufferSz = NI32(Mul, bufferLen, elSz);
+ auto indexPtr = Offset::New(bufferPtr, bufferSz);
+
+ sfx.SetLocalStatePointer(Offset::New(indexPtr, Native::Constant::New((int64_t)Type::Int32.GetSize())));
+
+ auto initIndex = Copy::New(indexPtr, Native::Constant::New(int32_t(0 - elementType.GetSize( ))),
Native::Constant::New(int32_t(4)), Copy::Store,
sfx.GetSymbolTable( ).GetInitializerReactivity( ), 1, true, true);
- indexDs = DataSource::New(
- Monad::New(indexDs->GetAccessor( ), initIndex),
- indexDs->GetDataLayout( ));
+ indexPtr = Deps::New(indexPtr, initIndex);
- auto initRbufProto = sfx.CopyData(state->First( )->First( ),
- sfx(GetUp(0)),
- sfx.GetSymbolTable( ).GetInitializerReactivity( ), true, true, true);
+ auto initRbufFirst = sfx.CopyData(
+ DataSource::New(bufferPtr,Reference::New(Native::Constant::New(elementType, nullptr))),
+ sfx(GetUp(0)),
+ sfx.GetSymbolTable().GetInitializerReactivity(), true, true, true);
- auto initRbufRest = Copy::New(state->First( )->Rest( )->GetAccessor( ),
- Monad::New(state->First( )->First( )->GetAccessor( ), initRbufProto),
- Native::Constant::New(int32_t(elementType.GetSize( ))), Copy::MemCpy,
- sfx.GetSymbolTable( ).GetInitializerReactivity( ), len - 1, true, true);
-
- auto index = Dereference::New(indexDs->GetAccessor( ), Type::Int32);
- auto newIdx(Native::MakeInt32("_add", Native::Add, index,
- Native::Constant::New(static_cast<int32_t>(elementType.GetSize()))));
+ auto initRbufRest =
+ Copy::New(
+ Offset::New(bufferPtr, elSz),
+ Deps::New(bufferPtr, initRbufFirst),
+ MakeConversionNode<int64_t,Native::ToInt64>(elSz, Type::Int32),
+ Copy::MemCpy,
+ sfx.GetSymbolTable().GetInitializerReactivity(),
+ NI32(Sub, bufferLen, Native::Constant::New((int32_t)1)), true, true);
- newIdx = Native::Select::New(newIdx, newIdx, Native::Constant::New(int32_t(0 - elementType.GetSize() * len)));
-
- auto updatedIndex(Monad::New(newIdx,
- Copy::New(indexDs->GetAccessor(), newIdx,
- Native::Constant::New(int32_t(4)), Copy::Mode::Store, GetReactivity(), 1, true, false)));
-
- auto initedRbufMemory = Monad::New(state->First( )->GetAccessor( ), initRbufRest);
+ auto index = Dereference::New(indexPtr, Type::Int32);
+ auto newIdx = NI32(Add, index, elSz);
+ newIdx = Native::Select::New(newIdx, newIdx,
+ NI32(Mul,
+ bufferLen,
+ Native::Constant::New(int32_t(0 - elementType.GetSize()))));
- bufferPtr = initedRbufMemory;
- evictPtr =
- Offset::New(GetAccessor(initedRbufMemory),
- Native::MakeInt32("_add", Native::Add, updatedIndex, Native::Constant::New(int32_t(elementType.GetSize()*len))));
+ auto updatedIndex(Deps::New(newIdx,
+ Copy::New(indexPtr, newIdx,
+ Native::Constant::New(int64_t(Type::Int32.GetSize())),
+ Copy::Mode::Store, GetReactivity(), 1, true, false)));
- rover = Native::MakeInt32("_div", Native::Div,
- Native::MakeInt32("_add", Native::Add, updatedIndex, Native::Constant::New(int32_t(elementType.GetSize()*len))),
- Native::Constant::New(int32_t(elementType.GetSize())));
+ bufferPtr = Deps::New(bufferPtr, initRbufRest);
+ auto bufferOffset = NI32(Add, updatedIndex, bufferSz);
+ evictPtr = Offset::New(bufferPtr, bufferOffset);
+
+ rover = NI32(Div, bufferOffset, elSz);
}
auto output(DataSource::New(evictPtr, Reference::New(Native::Constant::New(elementType, 0))));
sfx.AddSideEffect(output, GetUp(1), statePtr, GetReactivity(), elementType.GetSize());
- auto outputTuple(
- Pair::New(DataSource::New(bufferPtr, Reference::New(Native::Constant::New(Type::Chain(elementType, len, Type(false)), 0))),
- Pair::New(output, rover)));
+ CTRef bufferView;
+ switch (timeBase) {
+ case smp:
+ bufferView = DataSource::New(
+ bufferPtr,
+ Reference::New(
+ Native::Constant::New(
+ Type::List(elementType, len), 0)));
+ break;
+ case sec:
+ bufferView =
+ MakeSlice(sfx,
+ BitCast::New(Type::ArrayView(elementType), bufferPtr),
+ Native::Constant::New((int32_t)0),
+ bufferLen, GetReactivity());
+ break;
+ }
+
+ auto outputTuple =
+ Pair::New(bufferView,
+ Pair::New(output, rover));
return outputTuple;
}
- /* identity transform that removes monads */
+ /* identity transform that removes Depss */
class CalleeArgumentMap : public PartialTransform<Transform::Identity<const Typed>> {
public:
CalleeArgumentMap(CTRef root):PartialTransform(root) { }
CTRef operate(CTRef src) {
- if (IsOfExactType<Monad>(src)) return operate(src->GetUp(0));
+ if (IsOfExactType<Deps>(src)) return operate(src->GetUp(0));
else return PartialTransform::operate(src);
}
};
@@ 1608,11 1935,11 @@ namespace K3
}
}
- static CTRef SetupParameterLeaf(SideEffectTransform& sfx, CTRef datum, size_t& ParamID, std::vector<CTRef>& callerParams, bool potentialTailCall) {
+ static CTRef SetupParameterLeaf(SideEffectTransform& sfx, CTRef datum, size_t& ParamID, std::vector<CTRef>& callerParams, bool input, bool potentialTailCall) {
if (IsPair(datum)) {
return Pair::New(
- SetupParameterLeaf(sfx, datum->GraphFirst(), ParamID, callerParams, potentialTailCall),
- SetupParameterLeaf(sfx, datum->GraphRest(), ParamID, callerParams, potentialTailCall));
+ SetupParameterLeaf(sfx, datum->GraphFirst(), ParamID, callerParams, input, potentialTailCall),
+ SetupParameterLeaf(sfx, datum->GraphRest(), ParamID, callerParams, input, potentialTailCall));
} else if (MayHaveData(datum)) {
DataSource *buf_ds;
IFixedResultType *layout;
@@ 1622,19 1949,19 @@ namespace K3
return GetDereferencedParams(sfx, layout->FixedResult(), datum, callerParams, ParamID);
} else {
callerParams.push_back(sfx.GetDataAccessor(datum));
- return DataSource::New(SubroutineArgument::In(ParamID++, datum), sfx.GetDataLayout(datum));
+ return DataSource::New(SubroutineArgument::New(input, ParamID++, datum), sfx.GetDataLayout(datum));
}
} else {
return Typed::Nil();
}
}
- static CTRef GetCallerAndCalleeParams(SideEffectTransform& sfx, CTRef pgraph, size_t& ParamID, std::vector<CTRef>& callerParams, bool potentialTailCall = false) {
+ static CTRef GetCallerAndCalleeParams(SideEffectTransform& sfx, CTRef pgraph, size_t& ParamID, std::vector<CTRef>& callerParams, bool input, bool potentialTailCall) {
if (IsPair(pgraph)) {
- auto f = GetCallerAndCalleeParams(sfx, pgraph->GraphFirst(), ParamID, callerParams, potentialTailCall);
- auto r = GetCallerAndCalleeParams(sfx, pgraph->GraphRest(), ParamID, callerParams, potentialTailCall);
+ auto f = GetCallerAndCalleeParams(sfx, pgraph->GraphFirst(), ParamID, callerParams, input, potentialTailCall);
+ auto r = GetCallerAndCalleeParams(sfx, pgraph->GraphRest(), ParamID, callerParams, input, potentialTailCall);
return Pair::New(f, r);
- } else return SetupParameterLeaf(sfx, sfx(pgraph), ParamID, callerParams, potentialTailCall);
+ } else return SetupParameterLeaf(sfx, sfx(pgraph), ParamID, callerParams, input, potentialTailCall);
}
static bool IsLayoutSimilar(CTRef a, CTRef b) {
@@ 1791,7 2118,7 @@ namespace K3
}
}
sfx.SetStatePointer(md);
- return Monad::New(result, md);
+ return Deps::New(result, md);
}
@@ 1805,19 2132,19 @@ namespace K3
//CalleeArgumentMap CalleeParams(GetUp(0)), CalleeResults(result);
std::vector<CTRef> CallerParams, CallerResults;
- CTRef ArgumentGraph = GetCallerAndCalleeParams(sfx, GetUp(0), ParamID, CallerParams);
+ CTRef ArgumentGraph = GetCallerAndCalleeParams(sfx, GetUp(0), ParamID, CallerParams, true, false);
if (ParamID > 8) {
CallerParams.clear(); ParamID = 1;
ArgumentGraph = GetCallerAndCalleeParams(sfx,
- Canonicalize(sfx(GetUp(0)), argumentReactivity, ArgumentType(), true, false, sfx), ParamID, CallerParams);
+ Canonicalize(sfx(GetUp(0)), argumentReactivity, ArgumentType(), true, false, sfx), ParamID, CallerParams, true, false);
}
- CTRef ResultGraph = GetCallerAndCalleeParams(sfx, result, ParamID, CallerResults);
+ CTRef ResultGraph = GetCallerAndCalleeParams(sfx, result, ParamID, CallerResults, false, false);
auto subroutine(Subroutine::New(GetLabel(), Typed::Nil()));
- sfx.CompileSubroutineAsync(subroutine, body,
+ sfx.CompileSubroutineAsync(label.c_str(), ArgumentType(), FixedResult(), subroutine, body,
SubstituteTypeToArgumentGraph(ArgumentGraph, Native::Constant::New(argumentType, 0)),
SubstituteTypeToArgumentGraph(ResultGraph, Native::Constant::New(FixedResult(), 0)));
@@ 1830,8 2157,8 @@ namespace K3
subroutine->ArgumentsConnected();
for (auto res : CallerResults) subroutine->Connect(res);
- /* return function result buffers with Monadic dependency on the subroutine call */
- return Monad::New(result, subroutine);
+ /* return function result buffers with Depsic dependency on the subroutine call */
+ return Deps::New(result, subroutine);
}
RecursionBranch::RecursionBranch(CTRef counter, CTRef up, int32_t* seq, Graph<Typed> t, Graph<Generic> a, Graph<Generic> r, CTRef calleeArgs, CTRef calleeRes, const FunctionSequence* parent)
@@ 1866,7 2193,7 @@ namespace K3
outPrepadAvailable--;
- return Monad::New(
+ return Deps::New(
DataSource::New(slot->GetAccessor(), prepad->GetDataLayout()),
sfx.CopyData(slot, sfx(p->GetUp(0)), 0, true,false,false));
} else {
@@ 1895,9 2222,9 @@ namespace K3
CTRef args = UsePrepadAllocation(sfx, GetUp(1));
std::vector<CTRef> CallerParams, CallerResults;
- CTRef ArgumentGraph = GetCallerAndCalleeParams(sfx, args, ParamID, CallerParams);
+ CTRef ArgumentGraph = GetCallerAndCalleeParams(sfx, args, ParamID, CallerParams, true, false);
- CTRef ResultGraph = GetCallerAndCalleeParams(sfx, Elision, ParamID, CallerResults);
+ CTRef ResultGraph = GetCallerAndCalleeParams(sfx, Elision, ParamID, CallerResults, false, false);
//std::cout << "Sequence Argument: " << *SequenceArgument << std::endl;
//std::cout << "RecursionBranch Argument: " << *ArgumentGraph << std::endl;
@@ 1917,7 2244,9 @@ namespace K3
Subroutine *recur = Subroutine::NewRecursive("recur", Typed::Nil(), *sequenceLength);
- sfx.CompileSubroutineAsync(recur, parentSeq->GetTailCall(),
+ sfx.CompileSubroutineAsync(
+ nullptr, Type::Nil, Type::Nil,
+ recur, parentSeq->GetTailCall(),
SubstituteTypeToArgumentGraph(ArgumentGraph, Native::Constant::New(tailArgType, 0)),
SubstituteTypeToArgumentGraph(ResultGraph, Native::Constant::New(tailResType, 0)));
@@ 1932,7 2261,7 @@ namespace K3
for (auto res : CallerResults) recur->Connect(res);
recur->Connect(sfx.GetDataAccessor(Counter));
- return Monad::New(Elision, recur);
+ return Deps::New(Elision, recur);
} else {
/* argument or result data map has changed; peel iteration out of loop */
if (parentSeq->GetRepeatCount() > 1) {
@@ 1961,10 2290,12 @@ namespace K3
CallerParams.clear(); CallerResults.clear();
ParamID = 1;
- ArgumentGraph = GetCallerAndCalleeParams(sfx, args, ParamID, CallerParams);
- ResultGraph = GetCallerAndCalleeParams(sfx, result, ParamID, CallerResults);
+ ArgumentGraph = GetCallerAndCalleeParams(sfx, args, ParamID, CallerParams, true, false);
+ ResultGraph = GetCallerAndCalleeParams(sfx, result, ParamID, CallerResults, false, false);
- sfx.CompileSubroutineAsync(recur, parentSeq->GetTailCall(),
+ sfx.CompileSubroutineAsync(
+ nullptr, Type::Nil, Type::Nil,
+ recur, parentSeq->GetTailCall(),
SubstituteTypeToArgumentGraph(ArgumentGraph, Native::Constant::New(tailArgType, 0)),
SubstituteTypeToArgumentGraph(ResultGraph, Native::Constant::New(tailResType, 0)));
@@ 1975,7 2306,7 @@ namespace K3
for (auto arg : CallerParams) recur->Connect(arg);
recur->ArgumentsConnected();
for (auto res : CallerResults) recur->Connect(res);
- return Monad::New(result, recur);
+ return Deps::New(result, recur);
}
}
KRONOS_UNREACHABLE;
@@ 1995,24 2326,23 @@ namespace K3
VariantTuple *vt;
if (argumentLayout->Cast(vt) && vt->GetRecurrenceDelta() > 0) {
- using namespace Nodes::Native;
CTRef passedArgsType = ReduceType(passedArgs);
CTRef elementType = ReduceType(vt->GetUp(0));
ResultTypeWithNoArgument rtnoa(nullptr);
- CTRef padding = MakeInt64("umul", Mul,
+ CTRef padding = NI64(Mul,
Native::Constant::New((int64_t)(elementType->Result(rtnoa).GetSize() * vt->GetRecurrenceDelta())),
seqLen);
- CTRef bufSize = MakeInt64("uadd", Add,
+ CTRef bufSize = NI64(Add,
padding, ComputeSize(passedArgsType));
CTRef paddedBuffer = Buffer::New(sfx, bufSize, Buffer::Stack, 16);
CTRef iteratorPtr = Offset::New(paddedBuffer, padding);
DataSource *iteratorDs = DataSource::New(iteratorPtr, Reference::New(passedArgsType));
- return Monad::New(iteratorDs, sfx.CopyData(iteratorDs, sfx(passedArgs), 0, true, false, false));
+ return Deps::New(iteratorDs, sfx.CopyData(iteratorDs, sfx(passedArgs), 0, true, false, false));
} else return 0;
}
@@ 2038,13 2368,13 @@ namespace K3
size_t ParamID(1);
std::vector<CTRef> CallerParams, CallerResults;
- CTRef ArgumentGraph = GetCallerAndCalleeParams(sfx, args, ParamID, CallerParams);
+ CTRef ArgumentGraph = GetCallerAndCalleeParams(sfx, args, ParamID, CallerParams, true, false);
if (ParamID > 8) {
CallerParams.clear(); ParamID = 1;
ArgumentGraph = GetCallerAndCalleeParams(sfx,
- Canonicalize(sfx(GetUp(0)), GetReactivity(), ArgumentType(), true, false, sfx), ParamID, CallerParams);
+ Canonicalize(sfx(GetUp(0)), GetReactivity(), ArgumentType(), true, false, sfx), ParamID, CallerParams, true, false);
}
- CTRef ResultGraph = GetCallerAndCalleeParams(sfx, result, ParamID, CallerResults);
+ CTRef ResultGraph = GetCallerAndCalleeParams(sfx, result, ParamID, CallerResults, false, false);
auto CounterArgument(SubroutineArgument::In(ParamID++, Type::Int32, "count"));
@@ 2068,7 2398,9 @@ namespace K3
CTRef body(builder.Go());
auto subroutine(Subroutine::New(GetLabel(), Typed::Nil()));
- sfx.CompileSubroutineAsync(subroutine, body,
+ sfx.CompileSubroutineAsync(
+ label, ArgumentType(), FixedResult(),
+ subroutine, body,
SubstituteTypeToArgumentGraph(ArgumentGraph, typedArgument),
SubstituteTypeToArgumentGraph(ResultGraph, typedResult), true);
@@ 2081,9 2413,25 @@ namespace K3
for (auto res : CallerResults) subroutine->Connect(res);
subroutine->Connect(Native::Constant::New(std::int32_t(0))); // recursion counter
- /* return function result buffers with Monadic dependency on the subroutine call */
- return Monad::New(result, subroutine);
+ /* return function result buffers with Depsic dependency on the subroutine call */
+ return Deps::New(result, subroutine);
}
};
#pragma endregion
+ CTRef Canonicalize(CTRef data, CRRef r, const Type& e, bool referenced, bool mustCopy, SideEffectTransform& sfx) {
+ if (mustCopy == false) {
+ const DataSource* ds;
+ data = DereferenceAll(data);
+ if (data->Cast(ds) && ds->HasPairLayout() == false && IsFused(r)) {
+ if (referenced) {
+ if (ds->CanTakeReference()) return ds->Reference();
+ } else return ds;
+ }
+ }
+ auto buf(Buffer::New(sfx, e.GetSize(), Buffer::Stack));
+ auto buf_ds(DataSource::New(buf, Reference::New(Native::Constant::New(e, 0))));
+ auto val = Deps::New(buf_ds, sfx.CopyData(buf_ds, data, r, true, false, false));
+ if (!referenced) return DereferenceOnce(val);
+ else return val;
+ }
};
M src/backends/SideEffectCompiler.h +2 -2
@@ 101,7 101,7 @@ namespace K3 {
void AddSideEffect(CTRef WritePtr, CTRef WriteVal, CTRef ReadPtr, CRRef Reactivity, std::int64_t sizeIfKnown = 0);
- static Graph<Typed> Compile(IInstanceSymbolTable& symbols, const CTRef body, const CTRef args, const CTRef results);
+ static Graph<Typed> Compile(IInstanceSymbolTable& symbols, const CTRef body, const CTRef args, const CTRef results, const char *l, const Type& argTy, const Type& resTy);
static Graph<Typed> Compile(IInstanceSymbolTable& symbols, CTRef body, const Type& args, const Type& results); // unity-mapped, for C-callability
CTRef AllocateBuffer(CTRef size);
@@ 109,7 109,7 @@ namespace K3 {
CopyElisionTransform& GetElision() { return elision; }
CTRef GetArgument() { return arguments; }
- void CompileSubroutineAsync(Subroutine*, CTRef, CTRef, CTRef, bool synchronous = false);
+ void CompileSubroutineAsync(const char* l, const Type&, const Type&, Subroutine*, CTRef, CTRef, CTRef, bool synchronous = false);
};
};
M src/common/ssstring.cpp +10 -14
@@ 160,7 160,6 @@ class simple_string : public abstract_st
CRef<char_buffer> content;
size_t content_start;
size_t content_end;
- size_t _hash;
#define NATVIS_CTOR
#ifdef _MSC_VER
@@ 184,7 183,6 @@ class simple_string : public abstract_st
tmp->push_back(*data++);
}
content_end = tmp->size();
- make_hash();
content = std::move(tmp);
NATVIS_CTOR
@@ 195,19 193,17 @@ class simple_string : public abstract_st
u8len=0;
for(size_t i(content_start);i!=content_end;++i) if ((content->at(i)&0xc0)!=0x80) u8len++;
assert(content_end<=content->size() && "simple_string out of bounds");
- make_hash();
NATVIS_CTOR
}
- void make_hash()
- {
- _hash = 1;
- for(size_t i(content_start);i!=content_end;++i) _hash = (1 + _hash) * 2654435761;
- }
public:
- size_t hash() const {return _hash;}
+ size_t hash(size_t seed) const {
+ size_t h = seed;
+ for (size_t i(content_start); i != content_end; ++i) h = (1 + h) * 2654435761;
+ return h;
+ }
static Ref<simple_string> cons(const char *data) {return new simple_string(data);}
@@ 306,7 302,8 @@ class composite_string : public abstract
friend class abstract_string;
friend class string_iterator;
CRef<abstract_string> lhs,rhs;
- composite_string(const abstract_string* lhs, const abstract_string* rhs):lhs(lhs),rhs(rhs) {}
+ composite_string(const abstract_string* lhs, const abstract_string* rhs):lhs(lhs),rhs(rhs) {
+ }
protected:
const simple_string* segment_at(size_t &offset) const
{
@@ 367,9 364,8 @@ public:
rhs->stream(out);
}
- size_t hash() const
- {
- return ((lhs->hash() + 1) * 2654435761) + rhs->hash();
+ size_t hash(size_t seed) const {
+ return rhs->hash(lhs->hash(seed));
}
};
@@ 388,7 384,7 @@ CRef<abstract_string> abstract_string::u
return a->compare(*b)<0;
}};*/
- struct hsh{size_t operator()(const abstract_string* a) const {return a->hash();}};
+ struct hsh{size_t operator()(const abstract_string* a) const {return a->hash(1);}};
struct cmp{bool operator()(const abstract_string* a, const abstract_string *b) const {return a->compare(*b)==0;}};
static unordered_set<CRef<abstract_string>,hsh,cmp> memoized_strings;
M src/common/ssstring.h +2 -2
@@ 47,7 47,7 @@ public:
virtual int compare(const abstract_string& rhs) const = 0;
virtual int compare(const simple_string& rhs) const = 0;
virtual void stream(std::ostream& out) const = 0;
- virtual size_t hash() const = 0;
+ virtual size_t hash(size_t seed = 1) const = 0;
string_iterator seek(size_t offset);
string_iterator begin() {return seek(0);}
string_iterator end() {return seek(asciilen());}
@@ 69,5 69,5 @@ static bool operator!=(CRef<SString>& a,
namespace std
{
- template <> struct hash<Ref<SString>> { size_t operator()(Ref<SString> s) const {return s->hash();} };
+ template <> struct hash<Ref<SString>> { size_t operator()(Ref<SString> s) const {return s->hash(1);} };
};
M src/driver/LanguageServer.cpp +1 -6
@@ 652,11 652,6 @@ namespace Kronos {
sym = sym.substr(lastColon + 1);
}
- auto remainder = c.first;
- if (remainder.compare(0, prefix.length(), prefix) == 0) {
- remainder = remainder.substr(prefix.length());
- }
-
switch (c.second.kind) {
default:
completionItems.emplace_back(object{
@@ 669,7 664,7 @@ namespace Kronos {
completionItems.emplace_back(object{
{ "label", c.first },
{ "kind", (double)c.second.kind },
- { "insertText", remainder + "(" + c.second.argSnippet + ")" },
+ { "insertText", c.first + "(" + c.second.argSnippet + ")" },
{ "insertTextFormat", 2.0 },
{ "sortText", sym },
{ "documentation", c.second.doc }
M src/driver/ReplEnvironment.cpp +6 -15
@@ 20,7 20,7 @@ namespace Kronos {
std::vector<GenericGraph> Compiler::Parse(const std::string& fragment, ChangeCallback changeCallback) {
std::vector<GenericGraph> results;
{
- LGuard lg(contextLock);
+ std::lock_guard<std::recursive_mutex> lg(contextLock);
cx.Parse(fragment.c_str(), true, [&results](const char *sym, GenericGraph imm) {
results.emplace_back(std::move(imm));
});
@@ 156,7 156,7 @@ namespace Kronos {
}
void Compiler::Invalidate(std::int64_t buildTy, BuildFlags flags) {
- LGuard lg(contextLock);
+ std::lock_guard<std::recursive_mutex> lg(contextLock);
buildCache.update_in({ buildTy, flags }, [](auto v) {
return pcoll::none{};
});
@@ 208,14 208,14 @@ namespace Kronos {
if (buildTask.closureUid == 0) {
return;
}
- LGuard lg{ contextLock };
+ std::lock_guard<std::recursive_mutex> lg{ contextLock };
Compile(buildTask);
}
});
}
int64_t Compiler::UID(const Type& t) {
- LGuard lg(contextLock);
+ std::lock_guard<std::recursive_mutex> lg(contextLock);
return cx.UIDFromType(t);
}
@@ 368,18 368,9 @@ namespace Kronos {
auto usec = Runtime::MicroSecTy(dur);
Runtime::VirtualTimePoint() = Runtime::TimePointTy(usec);
Runtime::ScriptContext sc(Runtime::Frozen);
-
-
- class_->construct(instanceMemory, useHost, closureData);
+ Connect(class_, instanceMemory, {});
+ class_->construct(instanceMemory, closureData);
class_->eval(instanceMemory, closureData, result.data.data());
-/* for (int i = 0; i < class_->num_symbols;++i) {
- auto &s{ class_->symbols[i] };
- if (strcmp(s.sym, "#:VM:World:World") == 0) {
- *class_->var(instanceMemory, s.slot_index) = &world;
- s.process(instanceMemory, alloca(class_->result_type_size), 1);
- }
- }*/
-
result.descriptor = class_->result_type_descriptor;
return result;
} catch (...) {
M src/driver/ReplEnvironment.h +5 -4
@@ 50,7 50,8 @@ namespace Kronos {
using BuildPostProcessor = std::function<void(ClassCode&)>;
class Compiler : public Runtime::IBuilder {
- std::mutex workQueueLock, contextLock;
+ std::mutex workQueueLock;
+ std::recursive_mutex contextLock;
Kronos::Context& cx;
using LGuard = std::lock_guard<std::mutex>;
std::condition_variable workAvailable;
@@ 105,20 106,20 @@ namespace Kronos {
int64_t NilUID() const { return 0ull; }
int64_t UID(const Type&);
void ExportLibraryMetadata(std::ostream& json) {
- LGuard lg(contextLock);
+ std::lock_guard<std::recursive_mutex> lg(contextLock);
cx.GetLibraryMetadataAsJSON(json);
}
void Invalidate(int64_t buildGraphTy, BuildFlags);
void SetDebugTrace(std::string flt) {
- LGuard lg(contextLock);
+ std::lock_guard<std::recursive_mutex> lg(contextLock);
cx.SetCompilerDebugTraceFilter(flt.c_str());
}
std::string GetSourceFilePosition(const char *token) {
if (!token) return "";
- LGuard lg(contextLock);
+ std::lock_guard<std::recursive_mutex> lg(contextLock);
return cx.GetModuleAndLineNumberText(token);
}
private:
M src/driver/TestInstrumentation.cpp +1 -1
@@ 125,7 125,7 @@ public:
}
void Subscribe(const MethodKey& mk, const ManagedRef& ref, krt_instance i, krt_process_call proc, const void** slot) override {
- if (mk == MethodKey{ "(audio Rate)" }) {
+ if (mk == MethodKey{ "#Rate{audio}" }) {
*slot = &dumpRate;
} else if (mk == MethodKey{ "audio" }) {
dumpAudioThread = [=]() { DumpProc(i, proc); };
M src/driver/clierror.cpp +1 -7
@@ 25,13 25,7 @@ std::string UnwrapException(const char*
out << em;
}
} else {
- const char unbound[] = "Unbound{";
- if (strncmp(txt, unbound, sizeof(unbound) - 1) == 0) {
- pos = strchr(txt, ' ');
- out << "Unbound symbol '" << std::string(txt + sizeof(unbound) - 1, pos) << "'";
- } else {
- out << txt;
- }
+ out << txt;
}
return out.str();
}
M src/driver/krpc.cpp +1 -0
@@ 50,6 50,7 @@ int main( int argn, const char *carg[] )
}
std::clog << "KRPC; Kronos " KRONOS_PACKAGE_VERSION " RPC Endpoint \n(c) 2018 Vesa Norilo, University of the Arts Helsinki\n\n";
+ std::clog << "[" << repo << " " << repoVersion << "]\n";
cx = CreateContext(Packages::BitbucketClient::ResolverCallback, &bbClient);
M src/k3/CompilerNodes.h +54 -22
@@ 4,7 4,7 @@
#include "Stateful.h"
#include "TypeAlgebra.h"
#include "Errors.h"
-
+#include "Native.h"
namespace K3 {
namespace Backends {
@@ 25,7 25,7 @@ namespace K3 {
END
/* metadata node for combining high level expression representation with a known pointer traversal path */
- TYPED_NODE(DataSource,TypedBinary)
+ TYPED_NODE(DataSource, TypedBinary)
DataSource(CTRef accessPath, CTRef dataLayout):TypedBinary(accessPath,dataLayout){}
PUBLIC
bool CanTakeReference() const;
@@ 53,7 53,7 @@ namespace K3 {
virtual int GetAlignment() const = 0;
};
- TYPED_NODE(SubroutineArgument,DisposableTypedLeaf,IFixedResultType,IAlignmentTrackerNode)
+ TYPED_NODE(SubroutineArgument,DisposableTypedLeaf,IAlignmentTrackerNode)
Type type;
size_t ID;
int pointerAlignment;
@@ 63,26 63,30 @@ namespace K3 {
SubroutineArgument(size_t ID, const char *l, bool isOutput, const Type& t, bool isReference, int pointerAlignment)
:ID(ID),isOutput(isOutput),type(t),isReference(isReference),label(l),pointerAlignment(pointerAlignment) {}
PUBLIC
- DEFAULT_LOCAL_COMPARE(DisposableTypedLeaf,ID,isOutput,pointerAlignment,type);
+ DEFAULT_LOCAL_COMPARE(DisposableTypedLeaf,ID,isOutput,isReference,pointerAlignment,type);
CODEGEN_EMITTER
unsigned ComputeLocalHash() const override;
- static CTRef In(size_t ID, CTRef fromGraph, const char *l = "in");
+ static CTRef In(size_t ID, CTRef fromGraph, const char *l = "in") {
+ return New(true, ID, fromGraph, l);
+ }
+ static CTRef Out(size_t ID, CTRef fromGraph, const char *l = "out") {
+ return New(false, ID, fromGraph, l);
+ }
static CTRef In(size_t ID, const Type& t, const char *l = "in")
{
assert(t.IsNativeType());
return new SubroutineArgument(ID+1,l,false,t,false,0);
}
+ static CTRef New(bool isInput, size_t ID, CTRef fromGraph, const char *l = nullptr);
static SubroutineArgument* Out(size_t ID, const Type& t, const char *l = "out") {return new SubroutineArgument(ID+1,l,true,t,false,0);}
static SubroutineArgument* In(size_t ID, int align, const char *l = "in") {return new SubroutineArgument(ID+1,l,false,Type::Nil,true,align);}
static SubroutineArgument* Out(size_t ID, int align, const char *l = "out") {return new SubroutineArgument(ID+1,l,true,Type::Nil,true,align);}
static SubroutineArgument* State() {return new SubroutineArgument(1,"state",false,Type::Nil,true,4);}
static SubroutineArgument* Self() {return new SubroutineArgument(0,"self",false,Type::Nil,true,16);}
Type Result(ResultTypeTransform&) const override {return type;}
- Type FixedResult() const override {return type;}
void Output(std::ostream& strm) const override;
-
size_t GetID() const {return ID;}
bool IsReference() const {return isReference;}
bool IsOutput() const {return isOutput;}
@@ 163,6 167,7 @@ namespace K3 {
PUBLIC
enum Allocation {
Stack,
+ StackZeroed,
Module,
Empty
};
@@ 216,7 221,9 @@ namespace K3 {
VariantTuple(CTRef elementType, CTRef elementCount, CTRef tail, int recurrenceDelta):TypedTernary(elementType,elementCount,tail),recurrenceDelta(recurrenceDelta){}
PUBLIC
DEFAULT_LOCAL_COMPARE(TypedTernary,recurrenceDelta);
- static VariantTuple* New(CTRef element, CTRef count, CTRef tail, int delta) {return new VariantTuple(element,count,tail,delta);}
+ static VariantTuple* New(CTRef element, CTRef count, CTRef tail, int delta) {
+ return new VariantTuple(element,count,tail,delta);
+ }
Type Result(ResultTypeTransform&) const override {INTERNAL_ERROR("not applicable");}
CTRef GraphFirst() const override;
CTRef GraphRest() const override;
@@ 280,33 287,38 @@ namespace K3 {
int SchedulingPriority() const override { return 5; }
END
- TYPED_NODE(Copy,TypedTernary)
+ TYPED_NODE(Copy,TypedPolyadic)
PUBLIC
enum Mode{
MemCpy,
Store
};
PRIVATE
- size_t repeat;
Mode mode;
int dstAlign = 4, srcAlign = 4;
bool mutatesState;
bool doesInit;
- Copy(CTRef dst, CTRef src, CTRef size, Mode m, const Reactive::Node *r, size_t repeat, int sa, int da, bool mutate, bool init)
- :TypedTernary(dst, src, size), repeat(repeat), mode(m), mutatesState(mutate),srcAlign(sa),dstAlign(da),doesInit(init) {
+ Copy(CTRef dst, CTRef src, CTRef size, CTRef repeat, Mode m, const Reactive::Node *r, int sa, int da, bool mutate, bool init)
+ :mode(m), mutatesState(mutate),srcAlign(sa),dstAlign(da),doesInit(init) {
+ Connect(dst); Connect(src); Connect(size); Connect(repeat);
SetReactivity(r);
}
PUBLIC
- DEFAULT_LOCAL_COMPARE(TypedTernary,mode,repeat,mutatesState,doesInit);
+ DEFAULT_LOCAL_COMPARE(TypedPolyadic,mode,mutatesState,doesInit);
CODEGEN_EMITTER
- static Copy* New(CTRef dst, CTRef src, CTRef sizeInBytes, Mode mode, const Reactive::Node* reactivity, size_t repeat, bool mutateState, bool doesInitialization) {
+ static Copy* New(CTRef dst, CTRef src, CTRef sizeInBytes, Mode mode, const Reactive::Node* reactivity, CTRef repeat, bool mutateState, bool doesInitialization) {
int sa = 0, da = 0;
IAlignmentTrackerNode *at;
if (src->Cast(at)) sa = at->GetAlignment();
if (dst->Cast(at)) da = at->GetAlignment();
- return new Copy(dst,src,sizeInBytes,mode,reactivity,repeat,sa,da,mutateState,doesInitialization);
+ return new Copy(dst,src,sizeInBytes,repeat,mode,reactivity,sa,da,mutateState,doesInitialization);
}
- Type Result(ResultTypeTransform&) const override {INTERNAL_ERROR("not implemented");}
+ static Copy* New(CTRef dst, CTRef src, CTRef sizeInBytes, Mode mode, const Reactive::Node* reactivity, size_t repeat, bool mutateState, bool doesInitialization) {
+ return New(dst, src, sizeInBytes, mode, reactivity, Native::Constant::New((int32_t)repeat), mutateState, doesInitialization);
+ }
+
+ Type Result(ResultTypeTransform&) const { return Type::Nil; }
+
void Output(std::ostream&) const override;
bool DoesMutateState() const { return mutatesState; }
@@ 315,19 327,39 @@ namespace K3 {
int SchedulingPriority() const override { return 5; }
END
- TYPED_NODE(Monad,TypedPolyadic)
+ TYPED_NODE(OnInit, TypedBinary)
+ OnInit(CTRef init, CTRef stream) :TypedBinary(init, stream) {}
+ PUBLIC
+ static OnInit* New(CTRef onInit, CTRef onStream) { return new OnInit(onInit, onStream); }
+ Type Result(ResultTypeTransform& rt) const override { return GetUp(0)->Result(rt); }
+ CODEGEN_EMITTER
+ END
+
+ TYPED_NODE(Configuration, DisposableTypedLeaf, IFixedResultType)
+ int slotIndex;
+ Type ty;
+ Configuration(Type t, int si) :slotIndex(si), ty(t) {}
+ PUBLIC
+ static Configuration* New(Type ty, int slotIndex) { return new Configuration{ ty, slotIndex }; }
+ Type Result(ResultTypeTransform&) const { return ty; }
+ Type FixedResult() const { return ty; }
+ int GetSlotIndex() const { return slotIndex; }
+ CODEGEN_EMITTER
+ END
+
+ TYPED_NODE(Deps,TypedPolyadic)
void ConnectUpstream() {};
template <typename... ARGS> void ConnectUpstream(CTRef up, ARGS... upstream) {
Connect(up);ConnectUpstream(upstream...);
}
bool isDataProtector;
- Monad(bool dp = false):isDataProtector(dp) { }
+ Deps(bool dp = false):isDataProtector(dp) { }
PUBLIC
DEFAULT_LOCAL_COMPARE(TypedPolyadic,isDataProtector);
CODEGEN_EMITTER
void Connect(CTRef upstream);
- static Monad* New(bool dataProtector = false) {return new Monad(dataProtector);}
- static CTRef Transfer(CTRef upstream, const Monad *dependencies);
+ static Deps* New(bool dataProtector = false) {return new Deps(dataProtector);}
+ static CTRef Transfer(CTRef upstream, const Deps *dependencies);
template <typename... ARGS> static CTRef New(CTRef initial, ARGS... upstream) {
DataSource *ds;
@@ 338,7 370,7 @@ namespace K3 {
np->SetReactivity(initial->GetReactivity( ));
return np;
}
- auto m(new Monad);
+ auto m(new Deps);
m->ConnectUpstream(initial,upstream...);
m->SetReactivity(initial->GetReactivity( ));
return m;
@@ 349,7 381,7 @@ namespace K3 {
return const_cast<Typed*>(New(const_cast<CTRef>(initial),upstream...));
}
- Type Result(ResultTypeTransform&t) const override {assert(GetNumCons() && "Incomplete Monad");return GetUp(0)->Result(t);}
+ Type Result(ResultTypeTransform&t) const override {assert(GetNumCons() && "Incomplete Deps");return GetUp(0)->Result(t);}
CTRef GraphFirst() const override;
CTRef GraphRest() const override;
M src/k3/Conversions.cpp +1 -0
@@ 78,6 78,7 @@ namespace K3 {
template <typename DST, int OPCODE>
CTRef MakeConversionNode(CTRef up, const Type& src)
{
+ assert(!up->Cast<IFixedResultType>() || up->Cast<IFixedResultType>()->FixedResult() == src);
if (src.IsFloat32()) return Cvt<DST,float,OPCODE>::New(up,1);
else if (src.IsFloat64()) return Cvt<DST,double,OPCODE>::New(up,1);
else if (src.IsInt32()) return Cvt<DST,int32_t,OPCODE>::New(up,1);
M src/k3/DynamicVariables.h +2 -0
@@ 19,6 19,7 @@ namespace K3 {
END
enum GlobalVarType {
+ Configuration,
Internal,
External,
Stream
@@ 66,6 67,7 @@ namespace K3 {
const Reactive::Node* ReactiveAnalyze(Reactive::Analysis&, const Reactive::Node**) const override;
CTRef ReactiveReconstruct(Reactive::Analysis&) const override;
bool IsExternal( ) const { return k == External; }
+ bool IsConfigurationSlot() const { return k == Configuration; }
bool IsStream() const { return k == Stream; }
Type GetKey() const { return key; }
int GetWeight() const override { return 2; }
M src/k3/Evaluate.cpp +1 -23
@@ 565,23 565,7 @@ namespace K3 {
RegionAllocator SpecializationAttemptAllocator;
Specialization spec;
- if (auto carg = A1.node->Cast<Native::Constant>()) {
- struct _cst : public SpecializationTransform {
- Specialization ConstantArgument;
- _cst(Specialization arg, CGRef root, SpecializationDiagnostic& rep)
- :SpecializationTransform(root, arg.result, rep), ConstantArgument(arg) { }
-
- Specialization operate(CGRef node) {
- if (IsOfExactType<GenericArgument>(node)) {
- return ConstantArgument;
- }
- return SpecializationTransform::operate(node);
- }
- };
-
- _cst ConstantPropagate{ A1, Form.GetGraph(), t.GetRep() };
- spec = ConstantPropagate.Go();
- } else if (recurPt) {
+ if (recurPt) {
struct _st : public SpecializationTransform {
const Type Form;
const std::vector<CGRef> *const recurPt;
@@ 663,12 647,6 @@ namespace K3 {
return make_pair(spec.node, spec.result);
}
} else if (Form.IsUserType()) {
- //if (Form.IsUserType(UnboundTag)) {
- // auto s(TypeError(&FatalFailure));
- // t.GetRep().Diagnostic(LogSpecializationBranches, this, Error::EmptyGraph, "Not a function");
- // return std::make_pair(s.node, s.result);
- //}
-
CGRef extEval = TLS::ResolveSymbol(":Fallback:Eval");
if (extEval) {
Evaluate tmp(":Fallback:Eval", extEval, GenericArgument::New());
M src/k3/FlowControl.cpp +54 -1
@@ 164,6 164,49 @@ namespace K3 {
}
}
+ Specialization GenericSlice::Specialize(SpecializationTransform& t) const {
+ SPECIALIZE_ARGS(t, 0, 1, 2);
+ auto vty = A0.result;
+ assert(A1.result.IsInt32());
+
+ Type elTy;
+ int staticLen = -1;
+
+ if (vty.IsPair()) {
+ auto head = vty.CountLeadingElements(vty.First());
+ auto tail = vty.Rest(head);
+ if (tail.IsNil() || tail == vty.First()) {
+ elTy = vty.First();
+ staticLen = vty.Arity().GetInvariantI64();
+ } else {
+ t.GetRep().Diagnostic(LogErrors, this, Error::InvalidType, A0.result, "Slice requires a homogeneous tuple or list");
+ return TypeError(&FatalFailure, Type("Slice requires a homogeneous tuple or list"));
+ }
+ } else if (vty.IsArrayView()) {
+ elTy = vty.GetArrayViewElement();
+ } else {
+ t.GetRep().Diagnostic(LogErrors, this, Error::InvalidType, A0.result, "Slice requires a homogeneous tuple or list");
+ return TypeError(&FatalFailure, Type("Slice requires a homogeneous tuple or list"));
+ }
+
+ auto len = A2.result;
+ if (len.IsInvariant()) {
+ if (len.GetInvariantI64() > std::numeric_limits<int>::max()) {
+ t.GetRep().Diagnostic(LogErrors, this, Error::BadInput, A2.result, "Slice length is too long");
+ return TypeError(&FatalFailure, Type::Pair(Type("Slice length is too long:"), len));
+ }
+ auto sa = SubArray::New((int)len.GetInvariantI64(), staticLen, elTy, A0.node, A1.node);
+ return Specialization(sa, sa->FixedResult());
+ } else if (len.IsInt32()) {
+ auto sa = Slice::New(staticLen, elTy, A0.node, A1.node, A2.node);
+ return Specialization(sa, sa->FixedResult());
+ } else {
+ SPECIALIZE(t, cvtInt, Convert::New(Convert::Int32, GetUp(2)));
+ auto sa = Slice::New(staticLen, elTy, A0.node, A1.node, cvtInt.node);
+ return Specialization(sa, sa->FixedResult());
+ }
+ }
+
CTRef AtIndex::IdentityTransform(GraphTransform<const Typed, CTRef>& transform) const {
return New(vectorTy, transform(GetUp(0)), transform(GetUp(1)));
}
@@ 185,7 228,11 @@ namespace K3 {
return vector->GraphFirst();
}
}
- return new AtIndex(vectorTy, vectorTy.First(), vectorTy.CountLeadingElements(vectorTy.First()), vector, index);
+ // count elements to select from
+ int count = vectorTy.CountLeadingElements(vectorTy.First());
+ if (vectorTy.Rest(count) == vectorTy.First()) ++count;
+
+ return new AtIndex(vectorTy, vectorTy.First(), count, vector, index);
// return new AtIndex(elementType, order, vector, index);
}
@@ 390,6 437,12 @@ namespace K3 {
GenericPair::New(maxi, idx)), zero)), lenc),
"vector index", "Selects an element from the homogeneous vector, clamping the index to the bounds");
+ pack.AddFunction("Slice", GenericSlice::New(
+ GenericFirst::New(Arg),
+ Convert::New(Convert::Int32, GenericFirst::New(GenericRest::New(Arg))),
+ GenericRest::New(GenericRest::New(Arg))
+ ));
+
pack.AddFunction("Select", GenericConstantSelect::New(Arg,false), "vector constant-index",
"Selects an element from the vector, clamping index to the bounds. 'constant-index' must be an invariant constant, but the contents of 'vector' do not need to be homogeneous.");
M src/k3/FlowControl.h +104 -40
@@ 9,75 9,138 @@ namespace K3 {
GENERIC_NODE(When,GenericPolyadic)
public:
static When* New() { return new When(); }
- END
+ END
- GENERIC_NODE(Polymorphic, GenericPolyadic)
+ GENERIC_NODE(Polymorphic, GenericPolyadic)
public:
static Polymorphic* New() { return new Polymorphic; }
- END
+ END
- GENERIC_NODE(GenericCond, GenericUnary)
+ GENERIC_NODE(GenericCond, GenericUnary)
GenericCond(CGRef a) :GenericUnary(a) {}
public:
static GenericCond* New(CGRef conditions) { return new GenericCond(conditions); }
END
- GENERIC_NODE(GenericDispatch, GenericUnary)
- GenericDispatch(CGRef args) :GenericUnary(args) {}
- PUBLIC
- static GenericDispatch* New(CGRef args) { return new GenericDispatch(args); }
- END
+ GENERIC_NODE(GenericDispatch, GenericUnary)
+ GenericDispatch(CGRef args) :GenericUnary(args) {}
+ PUBLIC
+ static GenericDispatch* New(CGRef args) { return new GenericDispatch(args); }
+ END
- GENERIC_NODE(GenericUnionSubtype, GenericUnary)
- int sti;
+ GENERIC_NODE(GenericUnionSubtype, GenericUnary)
+ int sti;
GenericUnionSubtype(CGRef data, int subTypeIndex) :sti(subTypeIndex), GenericUnary(data) {}
- PUBLIC
- static GenericUnionSubtype* New(CGRef data, int subTypeIndex) { return new GenericUnionSubtype(data, subTypeIndex); }
- END
+ PUBLIC
+ static GenericUnionSubtype* New(CGRef data, int subTypeIndex) { return new GenericUnionSubtype(data, subTypeIndex); }
+ END
- TYPED_NODE(UnsafePointerCast, DisposableTypedUnary, IFixedResultType)
- UnsafePointerCast(const Type t, CTRef p) : DisposableTypedUnary(p),t(t) {}
+ TYPED_NODE(UnsafePointerCast, DisposableTypedUnary, IFixedResultType)
+ UnsafePointerCast(const Type t, CTRef p) : DisposableTypedUnary(p), t(t) {}
Type t;
- PUBLIC
- static UnsafePointerCast* New(const Type& t, CTRef ptr) { return new UnsafePointerCast(t, ptr); }
+ PUBLIC
+ static UnsafePointerCast* New(const Type& t, CTRef ptr) { return new UnsafePointerCast(t, ptr); }
Type Result(ResultTypeTransform&) const override { return t; }
Type FixedResult() const override { return t; }
CTRef SideEffects(Backends::SideEffectTransform& sfx) const override;
- END
+ END
- GENERIC_NODE(Raise,GenericUnary)
- Raise(CGRef ex):GenericUnary(ex) {}
+ GENERIC_NODE(Raise, GenericUnary)
+ Raise(CGRef ex) :GenericUnary(ex) {}
public:
static Raise* New(CGRef exception) { return new Raise(exception); }
static Raise* NewFatalFailure(const char* msg, CGRef args = nullptr);
- END
+ END
- GENERIC_NODE(Handle,GenericBinary)
- Handle(CGRef ptry, CGRef pcatch):GenericBinary(ptry,pcatch) {}
+ GENERIC_NODE(Handle, GenericBinary)
+ Handle(CGRef ptry, CGRef pcatch) :GenericBinary(ptry, pcatch) {}
public:
- static Handle* New(CGRef tryGraph, CGRef catchGraph) { return new Handle(tryGraph,catchGraph); }
- END
+ static Handle* New(CGRef tryGraph, CGRef catchGraph) { return new Handle(tryGraph, catchGraph); }
+ END
+
+ GENERIC_NODE(GenericGetVectorLen, GenericUnary)
+ GenericGetVectorLen(CGRef sig) :GenericUnary(sig) {}
+ PUBLIC
+ static GenericGetVectorLen* New(CGRef sig) { return new GenericGetVectorLen(sig); }
+ END
+
+ GENERIC_NODE(GenericSelect, GenericTernary)
+ GenericSelect(CGRef vector, CGRef idx, CGRef max) : GenericTernary(vector, idx, max) {}
+ PUBLIC
+ static GenericSelect* New(CGRef vec, CGRef idx, CGRef max) { return new GenericSelect(vec, idx, max); }
+ END
+
+ GENERIC_NODE(GenericConstantSelect, GenericUnary)
+ bool wrap;
+ GenericConstantSelect(CGRef a, bool w) :wrap(w), GenericUnary(a) {}
+ PUBLIC
+ DEFAULT_LOCAL_COMPARE(GenericUnary, wrap);
+ static GenericConstantSelect* New(CGRef vecidx, bool wrap) { return new GenericConstantSelect(vecidx, wrap); }
+ END
+
+ GENERIC_NODE(GenericSlice, GenericTernary)
+ GenericSlice(CGRef vec, CGRef skip, CGRef take) :GenericTernary(vec, skip, take) {}
+ PUBLIC
+ static GenericSlice* New(CGRef vec, CGRef skip, CGRef take) { return new GenericSlice(vec, skip, take); }
+ END
- GENERIC_NODE(GenericGetVectorLen,GenericUnary)
- GenericGetVectorLen(CGRef sig):GenericUnary(sig) {}
+ GENERIC_NODE(GenericSliceArity, GenericUnary)
+ GenericSliceArity(CGRef vec) : GenericUnary(vec) {}
+ PUBLIC
+ static GenericSliceArity* New(CGRef vec) { return new GenericSliceArity(vec); }
+ END
+
+
+ struct SliceSource {
+ Type elementType;
+ int sourceLen;
+ Type GetElementType() const {
+ return elementType;
+ }
+
+ Type GetSourceArrayType() const {
+ return Type::List(elementType, sourceLen);
+ }
+ };
+
+ TYPED_NODE(Slice, DisposableTypedTernary, IFixedResultType)
+ SliceSource src;
+ Slice(int sl, Type et, CTRef vec, CTRef skip, CTRef take)
+ :src({et, sl})
+ ,DisposableTypedTernary(vec,skip,take) { }
PUBLIC
- static GenericGetVectorLen* New(CGRef sig) { return new GenericGetVectorLen(sig); }
+ DEFAULT_LOCAL_COMPARE(DisposableTypedTernary, src.elementType);
+ static Slice* New(int staticLen, Type buffer, CTRef vector, CTRef skip, CTRef take) {
+ return new Slice(staticLen, buffer, vector, skip, take);
+ }
+
+ Type FixedResult() const override { return Type::ArrayView(src.GetElementType()); }
+ Type Result(ResultTypeTransform&) const override { return Type::ArrayView(src.GetElementType()); }
+ CTRef SideEffects(Backends::SideEffectTransform& sfx) const override;
END
- GENERIC_NODE(GenericSelect,GenericTernary)
- GenericSelect(CGRef vector, CGRef idx, CGRef max):GenericTernary(vector,idx,max) {}
+ TYPED_NODE(SubArray, DisposableTypedBinary, IFixedResultType)
+ int sliceLen;
+ SliceSource src;
+ SubArray(int len, int sl, Type et, CTRef vec, CTRef skip)
+ :DisposableTypedBinary(vec, skip)
+ , src({ et, sl })
+ , sliceLen(len) {}
PUBLIC
- static GenericSelect* New(CGRef vec, CGRef idx, CGRef max) { return new GenericSelect(vec,idx,max); }
+ DEFAULT_LOCAL_COMPARE(DisposableTypedBinary, src.elementType, sliceLen);
+ static SubArray* New(int len, int srcLen, Type bt, CTRef vec, CTRef skip) {
+ return new SubArray(len, srcLen, bt, vec, skip);
+ }
+ Type FixedResult() const override {
+ return Type::Tuple(src.GetElementType(), sliceLen);
+ }
+ Type Result(ResultTypeTransform&) const override {
+ return FixedResult();
+ }
+ CTRef SideEffects(Backends::SideEffectTransform& sfx) const override;
END
- GENERIC_NODE(GenericConstantSelect, GenericUnary)
- bool wrap;
- GenericConstantSelect(CGRef a,bool w) :wrap(w),GenericUnary(a) {}
- PUBLIC
- DEFAULT_LOCAL_COMPARE(GenericUnary, wrap);
- static GenericConstantSelect* New(CGRef vecidx, bool wrap) { return new GenericConstantSelect(vecidx, wrap); }
- END
-
+
GENERIC_NODE(GenericTernaryAtom,GenericTernary)
GenericTernaryAtom(CGRef cond, CGRef whenTrue, CGRef whenFalse):GenericTernary(cond,whenTrue,whenFalse) {}
PUBLIC
@@ 100,6 163,7 @@ namespace K3 {
virtual int GetWeight() const override { return 2; }
END
+
TYPED_NODE(Switch, TypedPolyadic, IFixedResultType)
Type result;
std::vector<int> branchResultSubtypeIndex;
M src/k3/Invariant.cpp +21 -2
@@ 49,6 49,16 @@ namespace K3 {
return Specialization(Typed::Nil(),Type(A0.result == A1.result));
}
+ Specialization GenericOrdinalCompareType::Specialize(SpecializationTransform& t) const {
+ SPECIALIZE_ARGS(t, 0, 1);
+ // extract as little information from types as possible, in order to
+ // minimize the type rules created during recursive specialization
+ if (expectOrdinal == 0)
+ return Specialization(Typed::Nil(), Type(A0.result == A1.result));
+
+ return Specialization(Typed::Nil(), Type(A0.result.OrdinalCompare(A1.result) == expectOrdinal));
+ }
+
Specialization GenericRequire::Specialize(SpecializationState& t) const {
SPECIALIZE_ARGS(t,0,1);
return A1;
@@ 542,7 552,7 @@ namespace K3 {
Specialization GenericDependency::Specialize(SpecializationState& t) const {
SPECIALIZE(t, val, GetUp(0));
SPECIALIZE(t, effect, GetUp(1));
- return Specialization(Monad::New(val.node, effect.node), val.result.Fix());
+ return Specialization(Deps::New(val.node, effect.node), val.result.Fix());
}
Specialization GenericSpecializationCallback::Specialize(SpecializationState& t) const {
@@ 983,7 993,16 @@ namespace K3 {
AddBinary(pack, "Class-Of", Invariant::GenericClassOf::New(Arg),
"instance","Returns a type tag describing the type class of 'instance'");
- AddBinary(pack,"Equal-Type",Invariant::GenericEqualType::New(GenericFirst::New(Arg),GenericRest::New(Arg)),"a b","performs compile time deep comparison of two type structures and returns true if identical");
+ auto typeCmp = [Arg](int expectOrdinal) {
+ return Invariant::GenericOrdinalCompareType::New(
+ expectOrdinal,
+ GenericFirst::New(Arg),
+ GenericRest::New(Arg));
+ };
+
+ AddBinary(pack,"Equal-Type",typeCmp(0),"a b","performs compile time deep comparison of two type structures and returns true if identical");
+ AddBinary(pack, "Less-Type", typeCmp(-1), "a b", "provides ordering between two types at compile time");
+ AddBinary(pack, "Greater-Type", typeCmp(1), "a b", "provides ordering between two types at compile time");
pack.AddMacro("Constant",GenericTypeTag::New(&InvariantTag), false);
BuildInvariantStringOps(pack.AddPackage("String"));
M src/k3/Invariant.h +7 -0
@@ 67,6 67,13 @@ namespace K3 {
static GenericEqualType* New(CGRef a, CGRef b) { return new GenericEqualType(a,b); }
END
+ GENERIC_NODE(GenericOrdinalCompareType, GenericBinary)
+ int expectOrdinal;
+ GenericOrdinalCompareType(int expect, CGRef a, CGRef b) : GenericBinary(a, b), expectOrdinal(expect) {}
+ PUBLIC
+ static GenericOrdinalCompareType* New(int expectOrdinal, CGRef a, CGRef b) { return new GenericOrdinalCompareType(expectOrdinal, a, b); }
+ END
+
GENERIC_NODE(ReplicateFirst,DisposableGenericBinary,IInversible)
ReplicateFirst(CGRef count, const Type& element, CGRef chain, int delta):DisposableGenericBinary(count,chain),element(element.Fix()),recurrenceDelta(delta) {}
Type element;
M src/k3/LibraryRef.cpp +4 -6
@@ 74,9 74,8 @@ namespace K3 {
}
}
}
- std::stringstream ss;
- ss << std::hex << std::uintptr_t(GetRepositoryAddress());
- return Specialization(Typed::Nil(), Type::User(&UnboundTag, Type::Pair(Type(lookup.front().c_str()), Type(ss.str().c_str()))));
+ t.GetRep().Diagnostic(Verbosity::LogErrors, this, Error::UndefinedSymbol, "Undefined symbol '%s'.", lookup.front().c_str());
+ return TypeError(&FatalFailure, Type(("Unbound symbol '" + lookup.front() + "'").c_str()));
}
Specialization Symbol::Specialize(SpecializationState& t) const {
@@ 85,9 84,8 @@ namespace K3 {
sym.result.OutputText(symName);
auto s = TLS::ResolveSymbol(symName.str().c_str());
if (s) return t(s);
- std::stringstream ss;
- ss << std::hex << std::uintptr_t(GetRepositoryAddress());
- return Specialization(Typed::Nil(), Type::User(&UnboundTag, Type::Pair(Type(symName.str().c_str()), Type(ss.str().c_str()))));
+ t.GetRep().Diagnostic(Verbosity::LogErrors, this, Error::UndefinedSymbol, "Undefined symbol '%s'.",symName.str().c_str());
+ return TypeError(&FatalFailure, Type(("Unbound symbol '" + symName.str() + "'").c_str()));
}
};
M src/k3/Native.cpp +16 -2
@@ 317,6 317,19 @@ namespace K3 {
// return Get();
//}
+ template <typename T> bool TypeCheck(CTRef t, int vw = 1) {
+ if (auto c = t->Cast<IFixedResultType>()) {
+ auto t = c->FixedResult();
+ if (t.IsNativeVector()) {
+ return
+ t.GetVectorElement() == Type::FromNative<T>() &&
+ t.GetVectorWidth() == vw;
+ }
+ return (c->FixedResult() == Type::FromNative<T>() && vw == 1);
+ }
+ return true;
+ }
+
template <typename T> class TBin : public ITypedBinary {
REGION_ALLOC(TBin)
INHERIT_RENAME(TBin, ITypedBinary)
@@ 334,6 347,7 @@ namespace K3 {
}
static Typed* New(CTRef a, CTRef b, Native::Opcode op, std::uint8_t vectorWidth, T(*action)(T, T)) {
+ assert(TypeCheck<T>(a, vectorWidth) && TypeCheck<T>(b, vectorWidth));
Constant *ac, *bc;
if (a->Cast(ac) && b->Cast(bc) && ac->GetPointer() && bc->GetPointer()) {
T* src1 = (T*)ac->GetPointer();
@@ 393,6 407,7 @@ namespace K3 {
public:
DEFAULT_LOCAL_COMPARE(ITypedUnary, opcode, vec)
static Typed* New(CTRef a, Native::Opcode op, std::uint8_t vectorWidth, T(*action)(T)) {
+ assert(TypeCheck<T>(a, vectorWidth));
Constant *ac(nullptr);
if (action && a->Cast(ac) && ac->GetPointer()) {
std::vector<T> dest(vectorWidth);
@@ 727,7 742,7 @@ namespace K3 {
CTypes.push_back(cty);
KTypes.push_back(kty);
- Connect(kty.GetSize() > 0 ? source : Typed::Nil());
+ Connect((kty.GetSize() > 0 || source->GetNumCons() == 0) ? source : Typed::Nil());
return true;
}
@@ 821,7 836,6 @@ namespace K3 {
pack.AddMacro("Double", GenericTypeTag::New(Type::Float64.TypeOf().GetDescriptor()), false);
pack.AddMacro("Int32", GenericTypeTag::New(Type::Int32.TypeOf().GetDescriptor()), false);
pack.AddMacro("Int64", GenericTypeTag::New(Type::Int64.TypeOf().GetDescriptor()), false);
- pack.AddMacro("Unbound-Symbol", GenericTypeTag::New(&UnboundTag), false);
pack.AddMacro("Exception", GenericTypeTag::New(&UserException), false);
pack.AddMacro("Vector", GenericTypeTag::New(&VectorTag), false);
M src/k3/Parser.cpp +8 -6
@@ 150,7 150,7 @@ namespace K3 {
return destructure(defs, c, [rhs]() {return rhs;});
}
- static Err<CGRef> MakeRingBuffer(const std::vector<CGRef>& n) {
+ static Err<CGRef> MakeRingBuffer(RingBufferTimeBase tb, const std::vector<CGRef>& n) {
CGRef initializer;
CGRef order;
@@ 167,7 167,7 @@ namespace K3 {
return ParserError(nullptr, "rbuf must have two or three arguments; optional initializer, invariant order and signal input.");
}
- auto rb = GenericRingBuffer::New(initializer, order);
+ auto rb = GenericRingBuffer::New(tb, initializer, order);
rb->Connect(n.back());
return (CGRef)rb;
}
@@ 191,15 191,17 @@ namespace K3 {
{ "z-1", [](nrv n) -> Err<CGRef> {
GenericRingBuffer* rb;
switch (n.size()) {
- case 1: rb = GenericRingBuffer::New(Invariant::Constant::New(0), Invariant::Constant::New(1)); break;
- case 2: rb = GenericRingBuffer::New(n[0], Invariant::Constant::New(1)); break;
+ case 1: rb = GenericRingBuffer::New(smp, Invariant::Constant::New(0), Invariant::Constant::New(1)); break;
+ case 2: rb = GenericRingBuffer::New(smp, n[0], Invariant::Constant::New(1)); break;
default: return ParserError(nullptr, "z-1 must have one or two arguments; optional initializer and signal input."); break;
}
rb->Connect(n.back());
return GenericRingBuffer::rbuf(rb);
} },
- { "rbuf", [](nrv n) -> Err<CGRef> { auto rb = MakeRingBuffer(n); if (rb.err) return std::move(rb.err); else return GenericRingBuffer::rbuf(*rb); } },
- { "rcsbuf", [](nrv n) { return MakeRingBuffer(n); } },
+ { "rbuf", [](nrv n) -> Err<CGRef> { auto rb = MakeRingBuffer(smp, n); if (rb.err) return std::move(rb.err); else return GenericRingBuffer::rbuf(*rb); } },
+ { "rcsbuf", [](nrv n) { return MakeRingBuffer(smp, n); } },
+ { "tbuf", [](nrv n) -> Err<CGRef> { auto rb = MakeRingBuffer(sec, n); if (rb.err) return std::move(rb.err); else return GenericRingBuffer::rbuf(*rb); } },
+ { "tcsbuf", [](nrv n) { return MakeRingBuffer(sec, n); } },
{ "Specialization-Monitor", [](nrv n) -> Err<CGRef> {
CHECK_ARITY(2);
return GenericSpecializationCallback::New(n[0], n[1]);
M src/k3/Reactive.cpp +25 -26
@@ 14,6 14,7 @@
#include "Invariant.h"
#include "NativeVector.h"
#include "UserErrors.h"
+#include "kronos.h"
#include <cmath>
#include <algorithm>
#include <memory>
@@ 136,12 137,12 @@ namespace K3 {
return cpy;
}
- const Node* Monad::ReactiveAnalyze(Analysis& t, const Node** upRx) const {
+ const Node* Deps::ReactiveAnalyze(Analysis& t, const Node** upRx) const {
if (upRx[0]) return upRx[0];
else return nullptr;
}
- CTRef Monad::ReactiveReconstruct(Analysis& t) const {
+ CTRef Deps::ReactiveReconstruct(Analysis& t) const {
auto cpy = IdentityTransform(t);
const_cast<Typed*>(cpy)->SetReactivity(t.ReactivityOf(this));
return cpy;
@@ 164,14 165,6 @@ namespace K3 {
return cpy;
}
- const Node* Transaction::ReactiveAnalyze(Analysis& t, const Node** upRx) const {
- INTERNAL_ERROR("todo");
- }
-
- CTRef Transaction::ReactiveReconstruct(Analysis& t) const {
- INTERNAL_ERROR("todo");
- }
-
static void ReserveOutputSignalMasks(const Node* output, Analysis& a) {
for(auto dn : Qxx::FromGraph(output).OfType<DriverNode>()) {
DriverSignature dsig = dn->GetID();
@@ 470,7 463,7 @@ namespace K3 {
}
CTRef Gate::ReactiveReconstruct(Analysis &st) const {
- auto m = Monad::New( );
+ auto m = Deps::New( );
int bitIdx = st.GetSignalMask(GetUp(0));
m->SetReactivity(st.ReactivityOf(this));
m->Connect(st.Boundary(st(GetUp(1)), st.ReactivityOf(GetUp(1)), m->GetReactivity( )));
@@ 603,24 596,28 @@ namespace K3 {
const Node* BaseRate::ReactiveAnalyze(Reactive::Analysis& a, const Node** upRx) const {
if (upRx[0] == nullptr) return nullptr;
- DriverSet rateReactivity;
+ if ((TLS::GetCurrentFlags() & Kronos::BuildFlags::DynamicRateSupport) != 0) {
+ DriverSet rateReactivity;
- for(auto drv : Qxx::FromGraph(upRx[0])
- .OfType<DriverNode>()
- .Select([](const DriverNode* dn) { return dn->GetID(); })
- .Where([](const Type& t) { return t.IsUserType(Reactive::ReactiveDriver); })) {
+ for (auto drv : Qxx::FromGraph(upRx[0])
+ .OfType<DriverNode>()
+ .Select([](const DriverNode* dn) { return dn->GetID(); })
+ .Where([](const Type& t) { return t.IsUserType(Reactive::ReactiveDriver); })) {
- DriverSignature sig(drv);
+ DriverSignature sig(drv);
- if (sig.GetDriverClass() == DriverSignature::User) {
- DriverSignature rateSig(Type::Tuple(sig.GetMetadata(), Type("Rate")), Type(0));
- Type derivedId = rateSig;
- a.GetDelegate( ).RegisterDriver(derivedId, 1, 1);
- rateReactivity.Merge(a.GetDelegate( ), derivedId);
+ if (sig.GetDriverClass() == DriverSignature::User) {
+ DriverSignature rateSig(Type::User(&ReactiveRateTag, sig.GetMetadata()), Type(0));
+ Type derivedId = rateSig;
+ a.GetDelegate().RegisterDriver(derivedId, 1, 1);
+ rateReactivity.Merge(a.GetDelegate(), derivedId);
+ }
}
+
+ return a.Memoize(rateReactivity);
+ } else {
+ return a.GetLeafReactivity();
}
-
- return a.Memoize(rateReactivity);
}
CTRef BaseRate::ReactiveReconstruct(Analysis& a) const {
@@ 629,14 626,16 @@ namespace K3 {
for (auto d : Qxx::FromGraph(a.ReactivityOf(GetUp(0))).OfType<DriverNode>( )) {
DriverSignature sig(d->GetID( ));
if (sig.GetDriverClass( ) == DriverSignature::User) {
- auto rateSig = Type::Tuple(sig.GetMetadata(), Type("Rate"));
+ auto rateSig = Type::User(&ReactiveRateTag, sig.GetMetadata());
Typed* extRate = GetGlobalVariable::New(
TLS::GetCurrentInstance()->Memoize(rateSig),
Type::Float32,
rateSig,
std::make_pair(1, 1),
nullptr,
- External);
+ (TLS::GetCurrentFlags() & Kronos::DynamicRateSupport) != 0
+ ? External
+ : Configuration);
double ratio = sig.GetRatio( );
if (ratio != 1.0) extRate = Native::MakeFloat("mul", Native::Mul, extRate, Native::Constant::New((float)ratio));
M src/k3/Stateful.cpp +45 -96
@@ 9,79 9,6 @@
namespace K3 {
namespace Nodes {
- Specialization GenericTable::Specialize(SpecializationTransform& spec) const {
- SPECIALIZE(spec, init, GetUp(0));
- SPECIALIZE(spec, numTrans, GetUp(1));
-
- auto msg = "Table initializer must return a nil-terminated homogenic list";
- if (init.result.IsTuple() == false) {
- spec.GetRep().Diagnostic(Verbosity::LogErrors, GetUp(0), Error::BadStateDataSource, msg);
- return spec.GetRep().TypeError("Table", init.result, Type(msg));
- }
-
- Type et = init.result.First().Fix();
- size_t count = init.result.CountLeadingElements(et);
-
- if (init.result.Rest(count) != Type::Nil) {
- spec.GetRep().Diagnostic(Verbosity::LogErrors, GetUp(0), Error::BadStateDataSource, "Table initializer must return a nil-terminated homogenic list");
- return spec.GetRep().TypeError("Table", init.result, Type(msg));
- }
-
- if (numTrans.result.IsInvariant() == false) {
- spec.GetRep().Diagnostic(Verbosity::LogErrors, GetUp(1), Error::BadStateDataSource, "Transaction count must be specified as an invariant constant");
- return spec.GetRep().TypeError("Table", numTrans.result, Type("Transaction count must be an invariant constant"));
- }
-
- Memory *mem = Memory::New(count, et, init.node);
- vector<Transaction*> pendingTransactions((size_t)numTrans.result.GetInvariant());
-
- CTRef transactResults = Typed::Nil();
-
- for (auto &pt : pendingTransactions) {
- pt = Transaction::New(1, mem, Typed::Nil(), Typed::Nil());
- transactResults = Pair::New(pt, transactResults);
- }
-
- spec.QueuePostProcessing([&spec, this, init, et, pendingTransactions](Specialization finalGraph) -> Specialization {
- SPECIALIZE(spec, transactions, GetUp(2));
-
- const Type expectedTransTy = Type::Chain(Type::Pair(Type::Int32, et), pendingTransactions.size(), Type::Nil);
- if (transactions.result != expectedTransTy) {
- spec.GetRep().Diagnostic(Verbosity::LogErrors, GetUp(2), Error::BadStateDataSource, transactions.result, expectedTransTy, "Table transaction has incorrect type");
- return spec.GetRep().TypeError("Table", transactions.result, Type::Pair(Type("Expected"), expectedTransTy));
- }
-
- Type tl = transactions.result.Fix();
- CTRef transNode = transactions.node;
-
- for (auto pt = pendingTransactions.rbegin(); pt != pendingTransactions.rend(); ++pt) {
-
- Type t = tl.First();
- CTRef tn = transNode->GraphFirst();
-
- (*pt)->Reconnect(1, tn->GraphFirst());
- (*pt)->Reconnect(2, tn->GraphRest());
-
- transNode = transNode->GraphRest();
- tl = tl.Rest();
- }
- return finalGraph;
- });
-
- return Specialization(Pair::New(mem, transactResults),
- Type::Pair(mem->FixedResult(), Type::Chain(et, pendingTransactions.size(), Type::Nil)));
- }
-
- CGRef GenericTable::IdentityTransform(GraphTransform<const Generic, CGRef>& copy) const {
- GenericTable *tbl = ConstructShallowCopy();
- tbl->Reconnect(0, copy(GetUp(0)));
- tbl->Reconnect(1, copy(GetUp(1)));
- copy.QueuePostProcessing([tbl, ©](CGRef g){
- tbl->Reconnect(2, copy(tbl->GetUp(2)));
- return g;
- });
- return tbl;
- }
class InitializerSynthesisTransform : public Transform::Identity<const Generic> {
std::unordered_set<const GenericRingBuffer*> decycle;
@@ 138,8 65,14 @@ namespace K3 {
if (order.result.IsInvariant()) {
Type et(init.result.Fix());
- size_t rb_order((size_t)(order.result.GetInvariant()));
- auto s(RingBuffer::New(rb_order,init.node,et));
+
+ auto len = order.result.GetInvariant();
+
+ // fixed point resolution in ca. usec
+ if (timeBase == sec) len *= (1 << 20);
+
+ size_t fpLen = (size_t)len;
+ auto s(RingBuffer::New(timeBase, fpLen, init.node, et));
spec.QueuePostProcessing([&spec,this,s,et,init, generatedInitializer](Specialization result) -> Specialization {
auto sig(spec(GetUp(2)));
@@ 164,11 97,18 @@ namespace K3 {
s->Connect(sig.node);
return result;
});
+
+ Type bufferType;
+ if (timeBase == smp) {
+ if (s->GetLen() > 1) bufferType = Type::List(et, s->GetLen());
+ else bufferType = et;
+ } else {
+ bufferType = Type::ArrayView(et);
+ }
return Specialization(s,
Type::Tuple(
- s->GetLen()>1 ? Type::Chain(et,s->GetLen(),Type(false))
- : et,
+ bufferType,
et,
Type::Int32));
} else {
@@ 231,24 171,33 @@ namespace K3 {
HASHER(h,elementType.GetHash());
return unsigned(h);
}
-
- CTRef Transaction::IdentityTransform(GraphTransform<const Typed, CTRef>& copy) const {
- auto trns = ConstructShallowCopy();
- trns->Reconnect(0, copy(trns->GetUp(0)));
- copy.QueuePostProcessing([trns, ©](CTRef g){
- for (unsigned int i = 1; i < trns->GetNumCons(); ++i) {
- trns->Reconnect(i, copy(trns->GetUp(i)));
- }
- return g;
- });
- return trns;
- }
-
- unsigned Memory::ComputeLocalHash() const {
- unsigned h = DisposableTypedUnary::ComputeLocalHash();
- HASHER(h, (unsigned)sz);
- HASHER(h, (unsigned)elTy.GetHash());
- return h;