diff --git a/compiler/generator/code_container.cpp b/compiler/generator/code_container.cpp index 25263cac1c..d4de7f4582 100644 --- a/compiler/generator/code_container.cpp +++ b/compiler/generator/code_container.cpp @@ -314,12 +314,12 @@ void CodeContainer::produceInfoFunctions(int tabs, const string& classname, cons generateGetOutputs(out_fun + classname, obj, ismethod, funtype)->accept(producer); } -void CodeContainer::generateDAGLoopInternal(CodeLoop* loop, BlockInst* block, DeclareVarInst* count, bool omp) +void CodeContainer::generateDAGLoopInternal(CodeLoop* loop, BlockInst* block, LoadVarInst* count, bool omp) { loop->generateDAGScalarLoop(block, count, omp); } -void CodeContainer::generateDAGLoopAux(CodeLoop* loop, BlockInst* loop_code, DeclareVarInst* count, int loop_num, +void CodeContainer::generateDAGLoopAux(CodeLoop* loop, BlockInst* loop_code, LoadVarInst* count, int loop_num, bool omp) { if (gGlobal->gFunTaskSwitch) { @@ -341,7 +341,7 @@ void CodeContainer::generateDAGLoopAux(CodeLoop* loop, BlockInst* loop_code, Dec } } -void CodeContainer::generateDAGLoop(BlockInst* block, DeclareVarInst* count) +void CodeContainer::generateDAGLoop(BlockInst* block, LoadVarInst* count) { int loop_num = 0; diff --git a/compiler/generator/code_container.hh b/compiler/generator/code_container.hh index 83d8ad283d..963f3d5663 100644 --- a/compiler/generator/code_container.hh +++ b/compiler/generator/code_container.hh @@ -181,9 +181,9 @@ class CodeContainer : public virtual Garbageable { merge(S, fLibrarySet); } - void generateDAGLoopAux(CodeLoop* loop, BlockInst* loop_code, DeclareVarInst* count, int loop_num, + void generateDAGLoopAux(CodeLoop* loop, BlockInst* loop_code, LoadVarInst* count, int loop_num, bool omp = false); - void generateDAGLoopInternal(CodeLoop* loop, BlockInst* block, DeclareVarInst* count, bool omp); + void generateDAGLoopInternal(CodeLoop* loop, BlockInst* block, LoadVarInst* count, bool omp); void includeFastMath() { @@ -364,7 +364,7 @@ class CodeContainer : public virtual Garbageable { void produceInfoFunctions(int tabs, const std::string& classname, const std::string& obj, bool ismethod, FunTyped::FunAttribute funtype, TextInstVisitor* producer, const std::string& in_fun = "getNumInputs", const std::string& out_fun = "getNumOutputs"); - void generateDAGLoop(BlockInst* loop_code, DeclareVarInst* count); + void generateDAGLoop(BlockInst* loop_code, LoadVarInst* count); template void generateMetaData(JSONUIReal* json) diff --git a/compiler/generator/cpp/cpp_gpu_code_container.cpp b/compiler/generator/cpp/cpp_gpu_code_container.cpp index 11738f0174..4a8434c93c 100644 --- a/compiler/generator/cpp/cpp_gpu_code_container.cpp +++ b/compiler/generator/cpp/cpp_gpu_code_container.cpp @@ -1075,13 +1075,13 @@ void CPPOpenCLVectorCodeContainer::generateComputeKernel(int n) int loop_num = 0; for (lclset::const_iterator p = dag[l].begin(); p != dag[l].end(); p++) { BlockInst* switch_case_block = InstBuilder::genBlockInst(); - generateDAGLoopAux(*p, switch_case_block, count_dec, loop_num); + generateDAGLoopAux(*p, switch_case_block, count_dec->load(), loop_num); switch_block->addCase(loop_num, switch_case_block); loop_num++; } } else { BlockInst* single_case_block = InstBuilder::genBlockInst(); - generateDAGLoopAux(*dag[l].begin(), single_case_block, count_dec, 0); + generateDAGLoopAux(*dag[l].begin(), single_case_block, count_dec->load(), 0); switch_block->addCase(0, single_case_block); } @@ -2016,13 +2016,13 @@ void CPPCUDAVectorCodeContainer::generateComputeKernel(int n) int loop_num = 0; for (lclset::const_iterator p = dag[l].begin(); p != dag[l].end(); p++) { BlockInst* switch_case_block = InstBuilder::genBlockInst(); - generateDAGLoopAux(*p, switch_case_block, count_dec, loop_num); + generateDAGLoopAux(*p, switch_case_block, count_dec->load(), loop_num); switch_block->addCase(loop_num, switch_case_block); loop_num++; } } else { BlockInst* single_case_block = InstBuilder::genBlockInst(); - generateDAGLoopAux(*dag[l].begin(), single_case_block, count_dec, 0); + generateDAGLoopAux(*dag[l].begin(), single_case_block, count_dec->load(), 0); switch_block->addCase(0, single_case_block); } diff --git a/compiler/generator/dag_instructions_compiler.hh b/compiler/generator/dag_instructions_compiler.hh index 6aea1dcc43..8517c77d0c 100644 --- a/compiler/generator/dag_instructions_compiler.hh +++ b/compiler/generator/dag_instructions_compiler.hh @@ -30,9 +30,11 @@ class DAGInstructionsCompiler : public InstructionsCompiler { virtual void compileMultiSignal(Tree sig); - private: + protected: // reimplemented code generation methods virtual ValueInst* CS(Tree sig); + + private: virtual ValueInst* generateCode(Tree sig); virtual void generateCodeRecursions(Tree sig); virtual ValueInst* generateCodeNonRec(Tree sig); @@ -50,7 +52,8 @@ class DAGInstructionsCompiler : public InstructionsCompiler { virtual ValueInst* generateInput(Tree sig, int idx); virtual ValueInst* generateDelay(Tree sig, Tree arg, Tree size); - virtual ValueInst* generateDelayVec(Tree sig, ValueInst* exp, Typed::VarType ctype, const std::string& vname, int mxd); + virtual ValueInst* generateDelayVec(Tree sig, ValueInst* exp, Typed::VarType ctype, const std::string& vname, + int mxd); virtual ValueInst* generateDelayLine(ValueInst* exp, Typed::VarType ctype, const std::string& vname, int mxd, Address::AccessType& access, ValueInst* ccs); diff --git a/compiler/generator/instructions.cpp b/compiler/generator/instructions.cpp index 5bab6c4af0..bcbfe8f0e7 100644 --- a/compiler/generator/instructions.cpp +++ b/compiler/generator/instructions.cpp @@ -164,19 +164,17 @@ DeclareVarInst::DeclareVarInst(Address* address, Typed* type, ValueInst* value) } // A list of channels variables also kept in the global name <===> type table (use in Rust and Julia backends) -DeclareBufferIterators::DeclareBufferIterators(const std::string& name1, - const std::string& name2, - int channels, - Typed* type, - bool mut) - : fBufferName1(name1), fBufferName2(name2), fChannels(channels), fType(type), fMutable(mut) +DeclareBufferIterators::DeclareBufferIterators(const std::string& name1, const std::string& name2, int channels, + Typed* type, bool mut, bool chunk) + : fBufferName1(name1), fBufferName2(name2), fChannels(channels), fType(type), fMutable(mut), fChunk(chunk) { for (int i = 0; i < channels; i++) { string chan_name = name1 + std::to_string(i); - if (gGlobal->gVarTypeTable.find(chan_name) == gGlobal->gVarTypeTable.end()) { + auto contains = gGlobal->gVarTypeTable.find(chan_name); + if (contains == gGlobal->gVarTypeTable.end()) { gGlobal->gVarTypeTable[chan_name] = type; } else { - faustassert(false); + faustassert(contains->second == type); } } } diff --git a/compiler/generator/instructions.hh b/compiler/generator/instructions.hh index 0e630d0712..2d1b989001 100644 --- a/compiler/generator/instructions.hh +++ b/compiler/generator/instructions.hh @@ -934,8 +934,9 @@ struct DeclareBufferIterators : public StatementInst { int fChannels; Typed* fType; bool fMutable; + bool fChunk; - DeclareBufferIterators(const std::string& name1, const std::string& name2, int channels, Typed* type, bool mut); + DeclareBufferIterators(const std::string& name1, const std::string& name2, int channels, Typed* type, bool mut, bool chunk); virtual ~DeclareBufferIterators() {} @@ -1484,7 +1485,7 @@ class BasicCloneVisitor : public CloneVisitor { } virtual StatementInst* visit(DeclareBufferIterators* inst) { - return new DeclareBufferIterators(inst->fBufferName1, inst->fBufferName2, inst->fChannels, inst->fType, inst->fMutable); + return new DeclareBufferIterators(inst->fBufferName1, inst->fBufferName2, inst->fChannels, inst->fType, inst->fMutable, inst->fChunk); } // Memory @@ -2079,9 +2080,9 @@ struct InstBuilder { return new DeclareStructTypeInst(type); } - static DeclareBufferIterators* genDeclareBufferIterators(const std::string& name1, const std::string& name2, int channels, Typed* type, bool mut) + static DeclareBufferIterators* genDeclareBufferIterators(const std::string& name1, const std::string& name2, int channels, Typed* type, bool mut, bool chunk = false) { - return new DeclareBufferIterators(name1, name2, channels, type, mut); + return new DeclareBufferIterators(name1, name2, channels, type, mut, chunk); } // Memory diff --git a/compiler/generator/omp_code_container.cpp b/compiler/generator/omp_code_container.cpp index 41954d2077..72b72368a5 100644 --- a/compiler/generator/omp_code_container.cpp +++ b/compiler/generator/omp_code_container.cpp @@ -130,7 +130,7 @@ StatementInst* OpenMPCodeContainer::generateDAGLoopOMP(const string& counter) BlockInst* omp_section_block = InstBuilder::genBlockInst(); if (dag[l].size() == 1) { // Only one loop if (!p->isRecursive() && gGlobal->gOpenMPLoop) { - generateDAGLoopAux(p, omp_section_block, count_dec, loop_num++, true); + generateDAGLoopAux(p, omp_section_block, count_dec->load(), loop_num++, true); } else { omp_section_block->setIndent(true); if (!is_single) { @@ -139,13 +139,13 @@ StatementInst* OpenMPCodeContainer::generateDAGLoopOMP(const string& counter) } else { omp_sections_block->pushBackInst(InstBuilder::genLabelInst("/* Still in a single section */")); } - generateDAGLoopAux(p, omp_section_block, count_dec, loop_num++); + generateDAGLoopAux(p, omp_section_block, count_dec->load(), loop_num++); } } else { is_single = false; omp_section_block->setIndent(true); omp_sections_block->pushBackInst(InstBuilder::genLabelInst("#pragma omp section")); - generateDAGLoopAux(p, omp_section_block, count_dec, loop_num++); + generateDAGLoopAux(p, omp_section_block, count_dec->load(), loop_num++); } omp_sections_block->pushBackInst(omp_section_block); } diff --git a/compiler/generator/rust/dag_instructions_compiler_rust.cpp b/compiler/generator/rust/dag_instructions_compiler_rust.cpp new file mode 100644 index 0000000000..8252c0e1b1 --- /dev/null +++ b/compiler/generator/rust/dag_instructions_compiler_rust.cpp @@ -0,0 +1,142 @@ +/************************************************************************ + ************************************************************************ + FAUST compiler + Copyright (C) 2017-2021 GRAME, Centre National de Creation Musicale + --------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************ + ************************************************************************/ + +#include "dag_instructions_compiler_rust.hh" +#include "fir_to_fir.hh" +#include "sigtyperules.hh" +#include "timing.hh" + +using std::string; + +void DAGInstructionsCompilerRust::compileMultiSignal(Tree L) +{ + startTiming("compileMultiSignal"); + + // Has to be done *after* gMachinePtrSize is set by the actual backend + gGlobal->initTypeSizeMap(); + + L = prepare(L); // Optimize, share and annotate expression + + Typed* type = InstBuilder::genBasicTyped(Typed::kFloatMacro_ptr); + pushComputeBlockMethod( + InstBuilder::genDeclareBufferIterators("input", "inputs", fContainer->inputs(), type, false, true)); + pushComputeBlockMethod( + InstBuilder::genDeclareBufferIterators("output", "outputs", fContainer->outputs(), type, true, true)); + + for (int index = 0; isList(L); L = tl(L), index++) { + Tree sig = hd(L); + string name = subst("output$0", T(index)); + + fContainer->openLoop("i"); + + // Possibly cast to external float + ValueInst* res = genCastedOutput(getCertifiedSigType(sig)->nature(), CS(sig)); + + if (gGlobal->gComputeMix) { + ValueInst* res1 = InstBuilder::genAdd(res, InstBuilder::genLoadArrayStackVar(name, getCurrentLoopIndex())); + pushComputeDSPMethod(InstBuilder::genStoreArrayStackVar(name, getCurrentLoopIndex(), res1)); + } else { + pushComputeDSPMethod(InstBuilder::genStoreArrayStackVar(name, getCurrentLoopIndex(), res)); + } + + fContainer->closeLoop(sig); + } + + generateUserInterfaceTree(fUITree.prepareUserInterfaceTree(), true); + generateMacroInterfaceTree("", fUITree.prepareUserInterfaceTree()); + if (fDescription) { + fDescription->ui(fUITree.prepareUserInterfaceTree()); + } + + // Apply FIR to FIR transformations + fContainer->processFIR(); + + endTiming("compileMultiSignal"); +} + +StatementInst* DAGInstructionsCompilerRust::generateInitArray(const string& vname, Typed::VarType ctype, int delay) +{ + ValueInst* init = InstBuilder::genTypedZero(ctype); + BasicTyped* typed = InstBuilder::genBasicTyped(ctype); + + // Generates table declaration + pushDeclare(InstBuilder::genDecStructVar(vname, InstBuilder::genArrayTyped(typed, delay))); + + Values args; + args.push_back(InstBuilder::genLoadStructVar(vname)); + args.push_back(init); + return InstBuilder::genVoidFunCallInst("fill", args, true); + + // ValueInst* init = InstBuilder::genTypedZero(ctype); + // BasicTyped* typed = InstBuilder::genBasicTyped(ctype); + // string index = gGlobal->getFreshID("l"); + // + // // Generates table declaration + // pushDeclare(InstBuilder::genDecStructVar(vname, InstBuilder::genArrayTyped(typed, delay))); + // + // ValueInst* upperBound = InstBuilder::genInt32NumInst(delay); + // // Generates init table loop + // SimpleForLoopInst* loop = InstBuilder::genSimpleForLoopInst(index, upperBound); + // + // LoadVarInst* loadVarInst = InstBuilder::genLoadVarInst(InstBuilder::genNamedAddress(index, Address::kLoop)); + // loop->pushFrontInst(InstBuilder::genStoreArrayStructVar(vname, loadVarInst, init)); + // return loop; +} + +StatementInst* DAGInstructionsCompilerRust::generateShiftArray(const string& vname, int delay) +{ + std::cout << "generateShiftArray " << vname << " " << delay << std::endl; + + string index = gGlobal->getFreshID("j"); + + ValueInst* upperBound = InstBuilder::genInt32NumInst(delay); + ValueInst* lowerBound = InstBuilder::genInt32NumInst(1); + + SimpleForLoopInst* loop = InstBuilder::genSimpleForLoopInst(index, upperBound, lowerBound, true); + LoadVarInst* loadVarInst = InstBuilder::genLoadVarInst(InstBuilder::genNamedAddress(index, Address::kLoop)); + ValueInst* load_value2 = InstBuilder::genSub(loadVarInst, InstBuilder::genInt32NumInst(1)); + ValueInst* load_value3 = InstBuilder::genLoadArrayStructVar(vname, load_value2); + + loop->pushFrontInst(InstBuilder::genStoreArrayStructVar(vname, loadVarInst, load_value3)); + return loop; +} + +StatementInst* DAGInstructionsCompilerRust::generateCopyArray(const string& vname_to, const string& vname_from, + int size) +{ + // std::cout << "generateCopyArray " << vname_to << " " << vname_from << " " << size << std::endl; + // Values args; + // args.push_back(InstBuilder::genLoadStackVar(vname_to)); + // args.push_back( + // InstBuilder::genLoadVarAddressInst(InstBuilder::genNamedAddress(vname_from, + // Address::AccessType::kStruct))); + // return InstBuilder::genVoidFunCallInst("copy_from_slice", args, true); + + string index = gGlobal->getFreshID("j"); + + ValueInst* upperBound = InstBuilder::genInt32NumInst(size); + SimpleForLoopInst* loop = InstBuilder::genSimpleForLoopInst(index, upperBound); + LoadVarInst* loadVarInst = InstBuilder::genLoadVarInst(InstBuilder::genNamedAddress(index, Address::kLoop)); + ValueInst* load_value = InstBuilder::genLoadArrayStructVar(vname_from, loadVarInst); + + loop->pushFrontInst(InstBuilder::genStoreArrayStackVar(vname_to, loadVarInst, load_value)); + return loop; +} diff --git a/compiler/generator/rust/dag_instructions_compiler_rust.hh b/compiler/generator/rust/dag_instructions_compiler_rust.hh new file mode 100644 index 0000000000..2537c80bf1 --- /dev/null +++ b/compiler/generator/rust/dag_instructions_compiler_rust.hh @@ -0,0 +1,39 @@ +/************************************************************************ + ************************************************************************ + FAUST compiler + Copyright (C) 2017-2021 GRAME, Centre National de Creation Musicale + --------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************ + ************************************************************************/ + +#ifndef FAUST_DAG_INSTRUCTIONS_COMPILER_RUST_H +#define FAUST_DAG_INSTRUCTIONS_COMPILER_RUST_H + +#include "dag_instructions_compiler.hh" + +class DAGInstructionsCompilerRust : public DAGInstructionsCompiler { + public: + DAGInstructionsCompilerRust(CodeContainer* container) : DAGInstructionsCompiler(container) {} + + void compileMultiSignal(Tree sig) override; + + private: + StatementInst* generateInitArray(const std::string& vname, Typed::VarType ctype, int delay) override; + StatementInst* generateShiftArray(const std::string& vname, int delay) override; + StatementInst* generateCopyArray(const std::string& vname_to, const std::string& vname_from, int size) override; +}; + +#endif // FAUST_DAG_INSTRUCTIONS_COMPILER_RUST_H diff --git a/compiler/generator/rust/rust_code_container.cpp b/compiler/generator/rust/rust_code_container.cpp index 4b2d89ddbb..c91936d9f4 100644 --- a/compiler/generator/rust/rust_code_container.cpp +++ b/compiler/generator/rust/rust_code_container.cpp @@ -20,11 +20,10 @@ ************************************************************************/ #include "rust_code_container.hh" -#include "Text.hh" #include "exception.hh" -#include "fir_function_builder.hh" #include "floats.hh" #include "global.hh" +#include "Text.hh" using namespace std; @@ -46,8 +45,8 @@ map RustInstVisitor::gFunctionSymbolTable; dsp_factory_base* RustCodeContainer::produceFactory() { return new text_dsp_factory_aux( - fKlassName, "", "", - ((dynamic_cast(fOut)) ? dynamic_cast(fOut)->str() : ""), ""); + fKlassName, "", "", ((dynamic_cast(fOut)) ? dynamic_cast(fOut)->str() : ""), + ""); } CodeContainer* RustCodeContainer::createScalarContainer(const string& name, int sub_container_type) @@ -55,6 +54,11 @@ CodeContainer* RustCodeContainer::createScalarContainer(const string& name, int return new RustScalarCodeContainer(name, 0, 1, fOut, sub_container_type); } +CodeContainer* RustCodeContainer::createVectorContainer(const string& name, int sub_container_type) +{ + return new RustVectorCodeContainer(name, 0, 1, fOut); +} + CodeContainer* RustCodeContainer::createContainer(const string& name, int numInputs, int numOutputs, ostream* dst) { gGlobal->gDSPStruct = true; @@ -75,8 +79,7 @@ CodeContainer* RustCodeContainer::createContainer(const string& name, int numInp } else if (gGlobal->gSchedulerSwitch) { throw faustexception("ERROR : Scheduler not supported for Rust\n"); } else if (gGlobal->gVectorSwitch) { - // container = new RustVectorCodeContainer(name, numInputs, numOutputs, dst); - throw faustexception("ERROR : Vector not supported for Rust\n"); + container = new RustVectorCodeContainer(name, numInputs, numOutputs, dst); } else { container = new RustScalarCodeContainer(name, numInputs, numOutputs, dst, kInt); } @@ -175,8 +178,10 @@ void RustCodeContainer::produceClass() tab(n, *fOut); *fOut << "#[cfg_attr(feature = \"default-boxed\", derive(default_boxed::DefaultBoxed))]"; - tab(n, *fOut); - *fOut << "#[repr(C)]"; + if (gGlobal->gReprC) { + tab(n, *fOut); + *fOut << "#[repr(C)]"; + } tab(n, *fOut); *fOut << "pub struct " << fKlassName << " {"; tab(n + 1, *fOut); @@ -214,7 +219,7 @@ void RustCodeContainer::produceClass() *fOut << "static void destroy" << fKlassName << "(" << fKlassName << "* dsp) {"; tab(n + 2, *fOut); fDestroyInstructions->accept(&fCodeProducer); - back(1, *fOut); + back(1, *fOut); *fOut << "}"; tab(n + 1, *fOut); } @@ -354,7 +359,7 @@ void RustCodeContainer::produceClass() tab(n, *fOut); *fOut << "}" << endl; tab(n, *fOut); - + // Generate user interface macros if needed printMacros(*fOut, n); } @@ -390,7 +395,8 @@ void RustCodeContainer::produceMetadata(int n) *fOut << "}" << endl; } -void RustCodeContainer::produceInfoFunctions(int tabs, const string& classname, const string& obj, bool ismethod, FunTyped::FunAttribute funtype, TextInstVisitor* producer) +void RustCodeContainer::produceInfoFunctions(int tabs, const string& classname, const string& obj, bool ismethod, + FunTyped::FunAttribute funtype, TextInstVisitor* producer) { producer->Tab(tabs); generateGetInputs(subst("get_num_inputs$0", classname), obj, false, funtype)->accept(&fCodeProducer); @@ -405,9 +411,9 @@ void RustCodeContainer::produceParameterGetterSetter(int tabs, map *fOut << "fn get_param(&self, param: ParamIndex) -> Option {"; tab(tabs + 1, *fOut); *fOut << "match param.0 {"; - for (const auto ¶mPair : parameterLookup) { + for (const auto& paramPair : parameterLookup) { const auto fieldName = paramPair.first; - const auto index = paramPair.second; + const auto index = paramPair.second; tab(tabs + 2, *fOut); *fOut << index << " => Some(self." << fieldName << "),"; } @@ -424,9 +430,9 @@ void RustCodeContainer::produceParameterGetterSetter(int tabs, map *fOut << "fn set_param(&mut self, param: ParamIndex, value: Self::T) {"; tab(tabs + 1, *fOut); *fOut << "match param.0 {"; - for (const auto ¶mPair : parameterLookup) { + for (const auto& paramPair : parameterLookup) { const auto fieldName = paramPair.first; - const auto index = paramPair.second; + const auto index = paramPair.second; tab(tabs + 2, *fOut); *fOut << index << " => { self." << fieldName << " = value }"; } @@ -469,7 +475,7 @@ void RustScalarCodeContainer::generateCompute(int n) } IteratorForLoopInst* loop = fCurLoop->generateSimpleScalarLoop(iterators); loop->accept(&fCodeProducer); - + // Currently for soundfile management generatePostComputeBlock(&fCodeProducer); @@ -481,6 +487,8 @@ void RustScalarCodeContainer::generateCompute(int n) RustVectorCodeContainer::RustVectorCodeContainer(const string& name, int numInputs, int numOutputs, std::ostream* out) : VectorCodeContainer(numInputs, numOutputs), RustCodeContainer(name, numInputs, numOutputs, out) { + // Required to not alias mutable buffers + gGlobal->gRemoveVarAddress = true; } void RustVectorCodeContainer::generateCompute(int n) @@ -492,6 +500,10 @@ void RustVectorCodeContainer::generateCompute(int n) // Compute declaration tab(n, *fOut); + *fOut << "#[allow(non_snake_case)]"; + tab(n, *fOut); + *fOut << "#[allow(unused_mut)]"; + tab(n, *fOut); *fOut << "fn compute(" << subst("&mut self, $0: i32, inputs: &[&[Self::T]], outputs: &mut[&mut[Self::T]]) {", fFullCount); tab(n + 1, *fOut); @@ -507,6 +519,43 @@ void RustVectorCodeContainer::generateCompute(int n) *fOut << "}" << endl; } +BlockInst* RustVectorCodeContainer::generateDAGLoopVariant0(const string& counter) +{ + // Define result block + BlockInst* block_res = InstBuilder::genBlockInst(); + + // declare vsize on top of the function + auto vsize_decl = InstBuilder::genDeclareVarInst(InstBuilder::genNamedAddress("vsize", Address::kConst), + InstBuilder::genBasicTyped(Typed::kInt32), + InstBuilder::genInt32NumInst(gGlobal->gVecSize)); + fComputeBlockInstructions->pushFrontInst(vsize_decl); + auto vsize = vsize_decl->load(); + + block_res->pushBackInst(InstBuilder::genLabelInst("/* Main loop */")); + BlockInst* loop_code = InstBuilder::genBlockInst(); + + // TODO(rust) use usize where needed instead of casting everywhere + // Generates the loop DAG + generateDAGLoop(loop_code, + InstBuilder::genLoadVarInst(InstBuilder::genNamedAddress("output0.len() as i32", Address::kStack))); + + std::vector iterators; + iterators.reserve(fNumInputs + fNumOutputs); + for (int i = 0; i < fNumInputs; ++i) { + iterators.push_back(InstBuilder::genNamedAddress("inputs" + std::to_string(i), Address::kStack)); + } + for (int i = 0; i < fNumOutputs; ++i) { + iterators.push_back(InstBuilder::genNamedAddress("outputs" + std::to_string(i), Address::kStack)); + } + + // Generates the DAG enclosing loop + StatementInst* loop = InstBuilder::genIteratorForLoopInst(iterators, false, loop_code); + + // Put loop in block_res + block_res->pushBackInst(loop); + return block_res; +} + // OpenMP RustOpenMPCodeContainer::RustOpenMPCodeContainer(const string& name, int numInputs, int numOutputs, std::ostream* out) : OpenMPCodeContainer(numInputs, numOutputs), RustCodeContainer(name, numInputs, numOutputs, out) diff --git a/compiler/generator/rust/rust_code_container.hh b/compiler/generator/rust/rust_code_container.hh index 76e4f05f28..dc9a7ef9e0 100644 --- a/compiler/generator/rust/rust_code_container.hh +++ b/compiler/generator/rust/rust_code_container.hh @@ -39,7 +39,7 @@ class RustCodeContainer : public virtual CodeContainer { std::ostream* fOut; void produceMetadata(int tabs); - + virtual void printHeader() { CodeContainer::printHeader(*fOut); } public: @@ -55,13 +55,15 @@ class RustCodeContainer : public virtual CodeContainer { virtual void generateCompute(int tab) = 0; void produceInternal(); virtual dsp_factory_base* produceFactory(); - virtual void produceInfoFunctions(int tabs, const std::string& classname, const std::string& obj, bool ismethod, FunTyped::FunAttribute funtype,TextInstVisitor* producer); - virtual void produceParameterGetterSetter(int tabs, std::map parameterLookup); + virtual void produceInfoFunctions(int tabs, const std::string& classname, const std::string& obj, bool ismethod, + FunTyped::FunAttribute funtype, TextInstVisitor* producer); + virtual void produceParameterGetterSetter(int tabs, std::map parameterLookup); CodeContainer* createScalarContainer(const std::string& name, int sub_container_type); + CodeContainer* createVectorContainer(const std::string& name, int sub_container_type); static CodeContainer* createContainer(const std::string& name, int numInputs, int numOutputs, - std::ostream* dst = new std::stringstream()); + std::ostream* dst = new std::stringstream()); }; class RustScalarCodeContainer : public RustCodeContainer { @@ -69,8 +71,7 @@ class RustScalarCodeContainer : public RustCodeContainer { public: RustScalarCodeContainer(const std::string& name, int numInputs, int numOutputs, std::ostream* out, int sub_container_type); - virtual ~RustScalarCodeContainer() - {} + virtual ~RustScalarCodeContainer() {} void generateCompute(int tab); }; @@ -79,18 +80,17 @@ class RustVectorCodeContainer : public VectorCodeContainer, public RustCodeConta protected: public: RustVectorCodeContainer(const std::string& name, int numInputs, int numOutputs, std::ostream* out); - virtual ~RustVectorCodeContainer() - {} + virtual ~RustVectorCodeContainer() {} - void generateCompute(int n); + void generateCompute(int n); + BlockInst* generateDAGLoopVariant0(const std::string& counter) override; }; class RustOpenMPCodeContainer : public OpenMPCodeContainer, public RustCodeContainer { protected: public: RustOpenMPCodeContainer(const std::string& name, int numInputs, int numOutputs, std::ostream* out); - virtual ~RustOpenMPCodeContainer() - {} + virtual ~RustOpenMPCodeContainer() {} void generateCompute(int tab); }; @@ -99,8 +99,7 @@ class RustWorkStealingCodeContainer : public WSSCodeContainer, public RustCodeCo protected: public: RustWorkStealingCodeContainer(const std::string& name, int numInputs, int numOutputs, std::ostream* out); - virtual ~RustWorkStealingCodeContainer() - {} + virtual ~RustWorkStealingCodeContainer() {} void generateCompute(int tab); }; diff --git a/compiler/generator/rust/rust_instructions.hh b/compiler/generator/rust/rust_instructions.hh index 46e6d13941..bc519433a0 100644 --- a/compiler/generator/rust/rust_instructions.hh +++ b/compiler/generator/rust/rust_instructions.hh @@ -24,14 +24,14 @@ #include -#include "text_instructions.hh" #include "Text.hh" +#include "text_instructions.hh" inline std::string makeNameSingular(const std::string& name) { std::string result = name; - result = std::regex_replace(result, std::regex("inputs"), "input"); - result = std::regex_replace(result, std::regex("outputs"), "output"); + result = std::regex_replace(result, std::regex("inputs"), "input"); + result = std::regex_replace(result, std::regex("outputs"), "output"); return result; } @@ -81,15 +81,13 @@ class RustInstVisitor : public TextInstVisitor { static std::map gFunctionSymbolTable; std::map fMathLibTable; // Integer wrapping operators - std::map fWrappingOpTable; - + std::map fWrappingOpTable; + // Function returning 'bool', to be casted to 'int' inline bool isBoolFun(const std::string& name) { - return (name == "F32::is_nan") - || (name == "F64::is_nan") - || (name == "F32::is_infinite") - || (name == "F64::is_infinite"); + return (name == "F32::is_nan") || (name == "F64::is_nan") || (name == "F32::is_infinite") || + (name == "F64::is_infinite"); } public: @@ -116,31 +114,31 @@ class RustInstVisitor : public TextInstVisitor { fMathLibTable["cosf"] = "F32::cos"; fMathLibTable["expf"] = "F32::exp"; fMathLibTable["floorf"] = "F32::floor"; - fMathLibTable["fmodf"] = "libm::fmodf"; + fMathLibTable["fmodf"] = "F32::rem"; fMathLibTable["logf"] = "F32::log"; fMathLibTable["log10f"] = "F32::log10"; fMathLibTable["max_f"] = "F32::max"; fMathLibTable["min_f"] = "F32::min"; fMathLibTable["powf"] = "F32::powf"; fMathLibTable["remainderf"] = "F32::rem_euclid"; - //fMathLibTable["rintf"] = "linux_api_math::rintf"; // TODO - fMathLibTable["rintf"] = "F32::round"; - fMathLibTable["roundf"] = "F32::round"; - fMathLibTable["sinf"] = "F32::sin"; - fMathLibTable["sqrtf"] = "F32::sqrt"; - fMathLibTable["tanf"] = "F32::tan"; + // fMathLibTable["rintf"] = "linux_api_math::rintf"; // TODO + fMathLibTable["rintf"] = "F32::round"; + fMathLibTable["roundf"] = "F32::round"; + fMathLibTable["sinf"] = "F32::sin"; + fMathLibTable["sqrtf"] = "F32::sqrt"; + fMathLibTable["tanf"] = "F32::tan"; // Additional hyperbolic math functions - fMathLibTable["acoshf"] = "F32::acosh"; - fMathLibTable["asinhf"] = "F32::asinh"; - fMathLibTable["atanhf"] = "F32::atanh"; - fMathLibTable["coshf"] = "F32::cosh"; - fMathLibTable["sinhf"] = "F32::sinh"; - fMathLibTable["tanhf"] = "F32::tanh"; - - fMathLibTable["isnanf"] = "F32::is_nan"; - fMathLibTable["isinff"] = "F32::is_infinite"; - fMathLibTable["copysignf"] = "F32::copysign"; + fMathLibTable["acoshf"] = "F32::acosh"; + fMathLibTable["asinhf"] = "F32::asinh"; + fMathLibTable["atanhf"] = "F32::atanh"; + fMathLibTable["coshf"] = "F32::cosh"; + fMathLibTable["sinhf"] = "F32::sinh"; + fMathLibTable["tanhf"] = "F32::tanh"; + + fMathLibTable["isnanf"] = "F32::is_nan"; + fMathLibTable["isinff"] = "F32::is_infinite"; + fMathLibTable["copysignf"] = "F32::copysign"; // Double version fMathLibTable["fabs"] = "F64::abs"; @@ -152,31 +150,31 @@ class RustInstVisitor : public TextInstVisitor { fMathLibTable["cos"] = "F64::cos"; fMathLibTable["exp"] = "F64::exp"; fMathLibTable["floor"] = "F64::floor"; - fMathLibTable["fmod"] = "libm::fmod"; + fMathLibTable["fmod"] = "F64::rem"; fMathLibTable["log"] = "F64::log"; fMathLibTable["log10"] = "F64::log10"; fMathLibTable["max_"] = "F64::max"; fMathLibTable["min_"] = "F64::min"; fMathLibTable["pow"] = "F64::powf"; fMathLibTable["remainder"] = "F64::rem_euclid"; - //fMathLibTable["rint"] = "linux_api_math::rint"; // TODO - fMathLibTable["rint"] = "F64::round"; - fMathLibTable["round"] = "F64::round"; - fMathLibTable["sin"] = "F64::sin"; - fMathLibTable["sqrt"] = "F64::sqrt"; - fMathLibTable["tan"] = "F64::tan"; + // fMathLibTable["rint"] = "linux_api_math::rint"; // TODO + fMathLibTable["rint"] = "F64::round"; + fMathLibTable["round"] = "F64::round"; + fMathLibTable["sin"] = "F64::sin"; + fMathLibTable["sqrt"] = "F64::sqrt"; + fMathLibTable["tan"] = "F64::tan"; // Additional hyperbolic math functions - fMathLibTable["acosh"] = "F64::acosh"; - fMathLibTable["asinh"] = "F64::asinh"; - fMathLibTable["atanh"] = "F64::atanh"; - fMathLibTable["cosh"] = "F64::cosh"; - fMathLibTable["sinh"] = "F64::sinh"; - fMathLibTable["tanh"] = "F64::tanh"; - - fMathLibTable["isnan"] = "F64::is_nan"; - fMathLibTable["isinf"] = "F64::is_infinite"; - fMathLibTable["copysign"] = "F64::copysign"; + fMathLibTable["acosh"] = "F64::acosh"; + fMathLibTable["asinh"] = "F64::asinh"; + fMathLibTable["atanh"] = "F64::atanh"; + fMathLibTable["cosh"] = "F64::cosh"; + fMathLibTable["sinh"] = "F64::sinh"; + fMathLibTable["tanh"] = "F64::tanh"; + + fMathLibTable["isnan"] = "F64::is_nan"; + fMathLibTable["isinf"] = "F64::is_infinite"; + fMathLibTable["copysign"] = "F64::copysign"; // Operations with a wrapping overflow behavior fWrappingOpTable[kAdd] = "wrapping_add"; @@ -190,10 +188,10 @@ class RustInstVisitor : public TextInstVisitor { { if (inst->fAddress->getAccess() & Address::kStaticStruct) { *fOut << "static mut "; - } - - if (inst->fAddress->getAccess() & Address::kStack || inst->fAddress->getAccess() & Address::kLoop) { + } else if (inst->fAddress->getAccess() & Address::kStack || inst->fAddress->getAccess() & Address::kLoop) { *fOut << "let mut "; + } else if (inst->getAccess() & Address::kConst) { + *fOut << "const "; } // If type is kNoType, only generate the name, otherwise a typed expression @@ -209,6 +207,10 @@ class RustInstVisitor : public TextInstVisitor { } else if (inst->fAddress->getAccess() & Address::kStaticStruct) { *fOut << " = "; RustInitFieldsVisitor::ZeroInitializer(fOut, inst->fType); + } else if (inst->getAccess() == Address::kStack && dynamic_cast(inst->fType)) { + // Initialize stack arrays to zero + *fOut << " = "; + RustInitFieldsVisitor::ZeroInitializer(fOut, inst->fType); } EndLine((inst->fAddress->getAccess() & Address::kStruct) ? ',' : ';'); @@ -225,10 +227,10 @@ class RustInstVisitor : public TextInstVisitor { panic!("wrong number of outputs"); }; */ - + // Don't generate if no channels if (inst->fChannels == 0) return; - + std::string name = inst->fBufferName2; // Build pattern matching + if let line @@ -251,9 +253,15 @@ class RustInstVisitor : public TextInstVisitor { tab(fTab, *fOut); *fOut << "let " << name << i << " = " << name << i << "[..count as usize]"; if (inst->fMutable) { - *fOut << ".iter_mut();"; + if (inst->fChunk) + *fOut << ".chunks_mut(vsize as usize);"; + else + *fOut << ".iter_mut();"; } else { - *fOut << ".iter();"; + if (inst->fChunk) + *fOut << ".chunks(vsize as usize);"; + else + *fOut << ".iter();"; } } @@ -359,9 +367,11 @@ class RustInstVisitor : public TextInstVisitor { *fOut << "]"; } else { // Array index expression casted to 'usize' type - *fOut << "[("; + *fOut << "["; + if (!indexed->getIndex()->isSimpleValue()) *fOut << "("; indexed->getIndex()->accept(this); - *fOut << ") as usize]"; + if (!indexed->getIndex()->isSimpleValue()) *fOut << ")"; + *fOut << " as usize]"; } } @@ -401,7 +411,7 @@ class RustInstVisitor : public TextInstVisitor { } *fOut << ']'; } - + virtual void visit(DoubleArrayNumInst* inst) { char sep = '['; @@ -411,17 +421,18 @@ class RustInstVisitor : public TextInstVisitor { } *fOut << ']'; } - + virtual void visit(BinopInst* inst) { + auto type1 = TypingVisitor::getType(inst->fInst1); + // Special case for 'logical right-shift' - if (strcmp(gBinOpTable[inst->fOpcode]->fName, ">>>") == 0) { - Typed::VarType type = TypingVisitor::getType(inst->fInst1); + if (inst->fOpcode == kLRsh) { *fOut << "((("; inst->fInst1->accept(this); - if (isInt64Type(type)) { + if (isInt64Type(type1)) { *fOut << " as u64)"; - } else if (isInt32Type(type)) { + } else if (isInt32Type(type1)) { *fOut << " as u32)"; } else { faustassert(false); @@ -429,27 +440,25 @@ class RustInstVisitor : public TextInstVisitor { *fOut << " >> "; inst->fInst2->accept(this); *fOut << ")"; - if (isInt64Type(type)) { + if (isInt64Type(type1)) { *fOut << " as i64)"; - } else if (isInt32Type(type)) { + } else if (isInt32Type(type1)) { *fOut << " as i32)"; } else { faustassert(false); } } else if (isBoolOpcode(inst->fOpcode)) { // Force cast to Int32 - *fOut << "(("; + *fOut << "("; TextInstVisitor::visit(inst); *fOut << ") as " << fTypeManager->generateType(InstBuilder::genInt32Typed()); - *fOut << ")"; - } else if (isIntType(TypingVisitor::getType(inst->fInst1)) && fWrappingOpTable.find(inst->fOpcode) != fWrappingOpTable.end()) { + } else if (isIntType(type1) && fWrappingOpTable.find(inst->fOpcode) != fWrappingOpTable.end()) { // Special case for integer add, sub and mul: // Overflowing is an error by default in Rust, but should wrap in Faust // Use their wrapping equivalent instead - Typed::VarType type = TypingVisitor::getType(inst->fInst1); - if (isInt32Type(type)) { + if (isInt32Type(type1)) { *fOut << "i32::"; - } else if (isInt64Type(type)) { + } else if (isInt64Type(type1)) { *fOut << "i64::"; } else { faustassert(false); @@ -467,23 +476,35 @@ class RustInstVisitor : public TextInstVisitor { virtual void visit(::CastInst* inst) { - *fOut << "(("; + bool needParentheses = dynamic_cast(inst->fInst) == nullptr; + if (needParentheses) *fOut << "("; inst->fInst->accept(this); - *fOut << ") as " << fTypeManager->generateType(inst->fType); - *fOut << ")"; + if (needParentheses) *fOut << ")"; + + // Cannot cast a boolean to a float directly, we must transition by an int + auto binop = dynamic_cast(inst->fInst); + if (binop && isBoolOpcode(binop->fOpcode) && inst->fType->getType() == Typed::kFloat) { + *fOut << " as u32 as " << fTypeManager->generateType(inst->fType); + } else if (binop && isBoolOpcode(binop->fOpcode) && inst->fType->getType() == Typed::kDouble) { + *fOut << " as u64 as " << fTypeManager->generateType(inst->fType); + } else { + *fOut << " as " << fTypeManager->generateType(inst->fType); + } } virtual void visit(BitcastInst* inst) { faustassert(false); } virtual void visit(FunCallInst* inst) { - if (fMathLibTable.find(inst->fName) != fMathLibTable.end()) { + if (inst->fName == "fmodf" || inst->fName == "fmod") { + InstBuilder::genRem(inst->fArgs.front(), inst->fArgs.back())->accept(this); + } else if (fMathLibTable.find(inst->fName) != fMathLibTable.end()) { generateFunCall(inst, fMathLibTable[inst->fName]); } else { generateFunCall(inst, inst->fName); } } - + virtual void generateFunCall(FunCallInst* inst, const std::string& fun_name) { if (inst->fMethod) { @@ -522,33 +543,28 @@ class RustInstVisitor : public TextInstVisitor { virtual void visit(Select2Inst* inst) { - *fOut << "if ("; + *fOut << "if "; inst->fCond->accept(this); - // Force 'cond' to bool type - *fOut << " as i32 != 0) { "; + *fOut << " != 0 {"; inst->fThen->accept(this); - *fOut << " } else { "; + *fOut << "} else {"; inst->fElse->accept(this); - *fOut << " }"; + *fOut << "}"; } virtual void visit(IfInst* inst) { - *fOut << "if ("; + *fOut << "if "; inst->fCond->accept(this); - // Force 'cond' to bool type - *fOut << " as i32 == 1) { "; - fTab++; - tab(fTab, *fOut); + *fOut << " != 0 {"; + tab(++fTab, *fOut); inst->fThen->accept(this); - fTab--; back(1, *fOut); - if (inst->fElse->fCode.size() > 0) { + if (!inst->fElse->fCode.empty()) { *fOut << "} else {"; - fTab++; - tab(fTab, *fOut); + tab(++fTab, *fOut); inst->fElse->accept(this); - fTab--; + fTab -= 1; back(1, *fOut); *fOut << "}"; } else { @@ -562,19 +578,50 @@ class RustInstVisitor : public TextInstVisitor { // Don't generate empty loops... if (inst->fCode->size() == 0) return; - inst->fInit->accept(this); - *fOut << "loop {"; - fTab++; - tab(fTab, *fOut); + auto init = dynamic_cast(inst->fInit); + std::string name; + ValueInst* value; + if (init) { + name = init->getName(); + value = init->fValue; + } else { + auto init = dynamic_cast(inst->fInit); + name = init->getName(); + value = init->fValue; + } + + auto increment = dynamic_cast(dynamic_cast(inst->fIncrement)->fValue)->fInst2; + bool increment_by_1 = false; + if (auto num = dynamic_cast(increment)) { + increment_by_1 = num->fNum == 1; + } + + auto end = dynamic_cast(inst->fEnd); + + *fOut << "for " << name << " in "; + if (!increment_by_1) *fOut << "("; + value->accept(this); + if (end->fOpcode == kLT) + *fOut << ".."; + else if (end->fOpcode == kLE) + *fOut << "..="; + else + throw faustexception("Unhandled opcode"); + end->fInst2->accept(this); + + // Increment + if (!increment_by_1) { + *fOut << ").step_by("; + increment->accept(this); + *fOut << ")"; + } + + *fOut << " {"; + tab(++fTab, *fOut); inst->fCode->accept(this); - inst->fIncrement->accept(this); - *fOut << "if "; - inst->fEnd->accept(this); - *fOut << " { continue; } else { break; }"; - fTab--; - tab(fTab, *fOut); + back(1, *fOut); *fOut << "}"; - tab(fTab, *fOut); + tab(--fTab, *fOut); } virtual void visit(SimpleForLoopInst* inst) @@ -676,21 +723,16 @@ class RustInstVisitor : public TextInstVisitor { class UserInterfaceParameterMapping : public DispatchVisitor { private: std::map fParameterLookup; - int fParameterIndex; + int fParameterIndex; public: using DispatchVisitor::visit; - UserInterfaceParameterMapping() - : DispatchVisitor(), fParameterLookup{}, fParameterIndex{0} - {} + UserInterfaceParameterMapping() : DispatchVisitor(), fParameterLookup{}, fParameterIndex{0} {} virtual ~UserInterfaceParameterMapping() {} - std::map getParameterLookup() - { - return fParameterLookup; - } + std::map getParameterLookup() { return fParameterLookup; } virtual void visit(AddMetaDeclareInst* inst) { @@ -722,7 +764,6 @@ class UserInterfaceParameterMapping : public DispatchVisitor { fParameterLookup[inst->fZone] = fParameterIndex++; } } - }; /** @@ -732,7 +773,8 @@ class RustUIInstVisitor : public TextInstVisitor { private: std::map fParameterLookup; - int getParameterIndex(const std::string& name) { + int getParameterIndex(const std::string& name) + { auto parameterIndex = fParameterLookup.find(name); if (parameterIndex == fParameterLookup.end()) { throw std::runtime_error("Parameter '" + name + "' is unknown"); @@ -744,23 +786,22 @@ class RustUIInstVisitor : public TextInstVisitor { public: using TextInstVisitor::visit; - RustUIInstVisitor(std::ostream* out, const std::string& structname, std::map parameterLookup, int tab = 0) - : TextInstVisitor(out, ".", new RustStringTypeManager(xfloat(), "&"), tab), - fParameterLookup{parameterLookup} - {} + RustUIInstVisitor(std::ostream* out, const std::string& structname, std::map parameterLookup, + int tab = 0) + : TextInstVisitor(out, ".", new RustStringTypeManager(xfloat(), "&"), tab), fParameterLookup{parameterLookup} + { + } - virtual ~RustUIInstVisitor() - {} + virtual ~RustUIInstVisitor() {} virtual void visit(AddMetaDeclareInst* inst) { // Special case if (inst->fZone == "0") { - *fOut << "ui_interface.declare(None, " << quote(inst->fKey) << ", " << quote(inst->fValue) - << ")"; + *fOut << "ui_interface.declare(None, " << quote(inst->fKey) << ", " << quote(inst->fValue) << ")"; } else { - *fOut << "ui_interface.declare(Some(ParamIndex(" << getParameterIndex(inst->fZone) << ")), " << quote(inst->fKey) << ", " - << quote(inst->fValue) << ")"; + *fOut << "ui_interface.declare(Some(ParamIndex(" << getParameterIndex(inst->fZone) << ")), " + << quote(inst->fKey) << ", " << quote(inst->fValue) << ")"; } EndLine(); } @@ -792,9 +833,11 @@ class RustUIInstVisitor : public TextInstVisitor { virtual void visit(AddButtonInst* inst) { if (inst->fType == AddButtonInst::kDefaultButton) { - *fOut << "ui_interface.add_button(" << quote(inst->fLabel) << ", ParamIndex(" << getParameterIndex(inst->fZone) << "))"; + *fOut << "ui_interface.add_button(" << quote(inst->fLabel) << ", ParamIndex(" + << getParameterIndex(inst->fZone) << "))"; } else { - *fOut << "ui_interface.add_check_button(" << quote(inst->fLabel) << ", ParamIndex(" << getParameterIndex(inst->fZone) << "))"; + *fOut << "ui_interface.add_check_button(" << quote(inst->fLabel) << ", ParamIndex(" + << getParameterIndex(inst->fZone) << "))"; } EndLine(); } @@ -814,8 +857,8 @@ class RustUIInstVisitor : public TextInstVisitor { break; } *fOut << name << "(" << quote(inst->fLabel) << ", " - << "ParamIndex(" << getParameterIndex(inst->fZone) << "), " << checkReal(inst->fInit) << ", " << checkReal(inst->fMin) << ", " - << checkReal(inst->fMax) << ", " << checkReal(inst->fStep) << ")"; + << "ParamIndex(" << getParameterIndex(inst->fZone) << "), " << checkReal(inst->fInit) << ", " + << checkReal(inst->fMin) << ", " << checkReal(inst->fMax) << ", " << checkReal(inst->fStep) << ")"; EndLine(); } @@ -830,11 +873,11 @@ class RustUIInstVisitor : public TextInstVisitor { name = "ui_interface.add_vertical_bargraph"; break; } - *fOut << name << "(" << quote(inst->fLabel) << ", ParamIndex(" << getParameterIndex(inst->fZone) << "), " << checkReal(inst->fMin) - << ", " << checkReal(inst->fMax) << ")"; + *fOut << name << "(" << quote(inst->fLabel) << ", ParamIndex(" << getParameterIndex(inst->fZone) << "), " + << checkReal(inst->fMin) << ", " << checkReal(inst->fMax) << ")"; EndLine(); } - + virtual void visit(AddSoundfileInst* inst) { // Not supported for now diff --git a/compiler/generator/struct_manager.hh b/compiler/generator/struct_manager.hh index bc5e1acb02..9ca1380ab0 100644 --- a/compiler/generator/struct_manager.hh +++ b/compiler/generator/struct_manager.hh @@ -34,51 +34,68 @@ struct MemoryDesc { // Location: kLocal for on chip (faster), kExternal for slower memory enum memType { kLocal, kExternal }; - int fFieldIndex; // Index in memory array - int fOffset; // Offset in bytes in a mixed int/real zone - int fIntOffset; // Offset in bytes in a separated int zone - int fRealOffset; // Offset in bytes in a separated real zone - int fRAccessCount; // Read access counter - int fWAccessCount; // Write access counter - int fSize; // Size in frames - int fSizeBytes; // Size in bytes - Typed::VarType fType; // FIR type - bool fIsConst; // True when constant - bool fIsControl; // True when control (slider, nentry, buttons, checkbox, bargraph) - memType fMemType; // Memory type - - MemoryDesc() : fFieldIndex(-1), fOffset(-1), - fIntOffset(-1), fRealOffset(-1), - fRAccessCount(0), fWAccessCount(0), - fSize(-1), fSizeBytes(-1), - fType(Typed::kNoType), - fIsConst(false), fIsControl(false), - fMemType(kLocal) {} + int fFieldIndex; // Index in memory array + int fOffset; // Offset in bytes in a mixed int/real zone + int fIntOffset; // Offset in bytes in a separated int zone + int fRealOffset; // Offset in bytes in a separated real zone + int fRAccessCount; // Read access counter + int fWAccessCount; // Write access counter + int fSize; // Size in frames + int fSizeBytes; // Size in bytes + Typed::VarType fType; // FIR type + bool fIsConst; // True when constant + bool fIsControl; // True when control (slider, nentry, buttons, checkbox, bargraph) + memType fMemType; // Memory type + + MemoryDesc() + : fFieldIndex(-1), + fOffset(-1), + fIntOffset(-1), + fRealOffset(-1), + fRAccessCount(0), + fWAccessCount(0), + fSize(-1), + fSizeBytes(-1), + fType(Typed::kNoType), + fIsConst(false), + fIsControl(false), + fMemType(kLocal) + { + } MemoryDesc(int index, int offset, int size, int size_bytes, Typed::VarType type) - : fFieldIndex(index), fOffset(offset), - fIntOffset(-1), fRealOffset(-1), - fRAccessCount(0), fWAccessCount(0), - fSize(size), fSizeBytes(size_bytes), - fType(type), - fIsConst(false), fIsControl(false), - fMemType(kLocal) {} - - MemoryDesc(int index, int offset, - int int_offset, int real_offset, - int size, int size_bytes, - Typed::VarType type, - bool is_const, - bool is_control, - memType mem_type = kLocal) - : fFieldIndex(index), fOffset(offset), - fIntOffset(int_offset), fRealOffset(real_offset), - fRAccessCount(0), fWAccessCount(0), - fSize(size), fSizeBytes(size_bytes), - fType(type), - fIsConst(is_const), fIsControl(is_control), - fMemType(mem_type) {} - + : fFieldIndex(index), + fOffset(offset), + fIntOffset(-1), + fRealOffset(-1), + fRAccessCount(0), + fWAccessCount(0), + fSize(size), + fSizeBytes(size_bytes), + fType(type), + fIsConst(false), + fIsControl(false), + fMemType(kLocal) + { + } + + MemoryDesc(int index, int offset, int int_offset, int real_offset, int size, int size_bytes, Typed::VarType type, + bool is_const, bool is_control, memType mem_type = kLocal) + : fFieldIndex(index), + fOffset(offset), + fIntOffset(int_offset), + fRealOffset(real_offset), + fRAccessCount(0), + fWAccessCount(0), + fSize(size), + fSizeBytes(size_bytes), + fType(type), + fIsConst(is_const), + fIsControl(is_control), + fMemType(mem_type) + { + } + Typed* getTyped() { if (fSize > 1) { @@ -93,18 +110,18 @@ struct MemoryDesc { Compute all fields info, the DSP size, and separate 'int' and 'real' types */ struct StructInstVisitor : public DispatchVisitor { - int fStructIntOffset; // Keep the int offset in bytes - int fStructRealOffset; // Keep the real offset in bytes - int fFieldIndex; // Keep the field index + int fStructIntOffset; // Keep the int offset in bytes + int fStructRealOffset; // Keep the real offset in bytes + int fFieldIndex; // Keep the field index MemoryDesc fDefault; - + // Vector is used so that field names are ordered in 'getStructType' typedef std::vector > field_table_type; - + field_table_type fFieldTable; // Table: field_name, MemoryDesc - + StructInstVisitor() : fStructIntOffset(0), fStructRealOffset(0), fFieldIndex(0) {} - + // Check if the field name exists bool hasField(const std::string& name, Typed::VarType& type) { @@ -116,7 +133,7 @@ struct StructInstVisitor : public DispatchVisitor { } return false; } - + // Return the offset of a given field in bytes int getFieldOffset(const std::string& name) { @@ -127,7 +144,7 @@ struct StructInstVisitor : public DispatchVisitor { faustassert(false); return -1; } - + // Return the int offset of a given field in bytes int getFieldIntOffset(const std::string& name) { @@ -138,7 +155,7 @@ struct StructInstVisitor : public DispatchVisitor { faustassert(false); return -1; } - + // Return the real offset of a given field in bytes int getFieldRealOffset(const std::string& name) { @@ -149,7 +166,7 @@ struct StructInstVisitor : public DispatchVisitor { faustassert(false); return -1; } - + // Return the index of a given field int getFieldIndex(const std::string& name) { @@ -160,7 +177,7 @@ struct StructInstVisitor : public DispatchVisitor { faustassert(false); return -1; } - + // Return the FIR type of a given field Typed::VarType getFieldType(const std::string& name) { @@ -171,7 +188,7 @@ struct StructInstVisitor : public DispatchVisitor { faustassert(false); return Typed::kNoType; } - + // Return the memory type of a given field MemoryDesc::memType getFieldMemoryType(const std::string& name) { @@ -182,7 +199,7 @@ struct StructInstVisitor : public DispatchVisitor { faustassert(false); return MemoryDesc::kLocal; } - + // Return the memory description of a given field MemoryDesc& getMemoryDesc(const std::string& name) { @@ -191,18 +208,18 @@ struct StructInstVisitor : public DispatchVisitor { } return fDefault; } - + // Return the struct 'int' size in bytes int getStructIntSize() { return fStructIntOffset; } - + // Return the struct 'real' size in bytes int getStructRealSize() { return fStructRealOffset; } - + // Return the struct size in bytes int getStructSize() { return fStructIntOffset + fStructRealOffset; } - + field_table_type& getFieldTable() { return fFieldTable; } - + int getArrayCount() { int res = 0; @@ -211,7 +228,7 @@ struct StructInstVisitor : public DispatchVisitor { } return res; } - + // Return the struct type DeclareStructTypeInst* getStructType(const std::string& name) { @@ -221,47 +238,37 @@ struct StructInstVisitor : public DispatchVisitor { } return InstBuilder::genDeclareStructTypeInst(InstBuilder::genStructTyped(name, dsp_type_fields)); } - + // Declarations void visit(DeclareVarInst* inst) { - std::string name = inst->fAddress->getName(); + std::string name = inst->fAddress->getName(); Address::AccessType access = inst->fAddress->getAccess(); - + bool is_struct = (access & Address::kStruct) || (access & Address::kStaticStruct); ArrayTyped* array_typed = dynamic_cast(inst->fType); - + if (array_typed && array_typed->fSize > 1) { Typed::VarType type = array_typed->fType->getType(); if (is_struct) { - fFieldTable.push_back(make_pair(name, MemoryDesc(fFieldIndex++, - getStructSize(), - getStructIntSize(), - getStructRealSize(), - array_typed->fSize, - array_typed->getSizeBytes(), - type, - false, false))); + fFieldTable.push_back( + make_pair(name, MemoryDesc(fFieldIndex++, getStructSize(), getStructIntSize(), getStructRealSize(), + array_typed->fSize, array_typed->getSizeBytes(), type, false, false))); if (type == Typed::kInt32) { fStructIntOffset += array_typed->getSizeBytes(); } else { fStructRealOffset += array_typed->getSizeBytes(); } - } else { - // Should never happen... - faustassert(false); - } + } /* else { + // Should never happen... + faustassert(false); + }*/ } else { if (is_struct) { - fFieldTable.push_back(make_pair(name, MemoryDesc(fFieldIndex++, - getStructSize(), - getStructIntSize(), - getStructRealSize(), - 1, - inst->fType->getSizeBytes(), - inst->fType->getType(), - isConst(name), - isControl(name)))); + fFieldTable.push_back(make_pair( + name, + MemoryDesc(fFieldIndex++, getStructSize(), getStructIntSize(), getStructRealSize(), 1, + inst->fType->getSizeBytes(), inst->fType->getType(), isConst(name), isControl(name)))); if (inst->fType->getType() == Typed::kInt32) { fStructIntOffset += inst->fType->getSizeBytes(); } else { @@ -269,23 +276,22 @@ struct StructInstVisitor : public DispatchVisitor { } } } - + if (inst->fValue) getMemoryDesc(inst->getName()).fWAccessCount++; DispatchVisitor::visit(inst); } - + void visit(LoadVarInst* inst) { getMemoryDesc(inst->getName()).fRAccessCount++; DispatchVisitor::visit(inst); } - + void visit(StoreVarInst* inst) { getMemoryDesc(inst->getName()).fWAccessCount++; DispatchVisitor::visit(inst); } - }; /* @@ -296,43 +302,37 @@ struct StructInstVisitor : public DispatchVisitor { - then other big arrays are kept in the DSP struct */ struct StructInstVisitor1 : public StructInstVisitor { - int fExternalMemory; int fDLThreshold; - + // To be computed with DSP struct size and FAUST_MAX_SIZE StructInstVisitor1(int external_memory, int dl_threshold = 4) - : StructInstVisitor(), fExternalMemory(external_memory), fDLThreshold(dl_threshold) - {} - + : StructInstVisitor(), fExternalMemory(external_memory), fDLThreshold(dl_threshold) + { + } + // Declarations void visit(DeclareVarInst* inst) { std::string name = inst->fAddress->getName(); Address::AccessType access = inst->fAddress->getAccess(); - + bool is_struct = (access & Address::kStruct) || (access & Address::kStaticStruct); ArrayTyped* array_typed = dynamic_cast(inst->fType); - + if (array_typed && array_typed->fSize > 1) { Typed::VarType type = array_typed->fType->getType(); if (is_struct) { // Arrays are allocated in iZone/fZone until fExternalMemory reaches 0 // kStaticStruct are always allocated in kExternal // RW tables ("itblXX" and "ftblXX") are always allocated in kExternal - if ((access & Address::kStaticStruct) - || isTable(name) - || (fExternalMemory > 0 && array_typed->fSize > fDLThreshold)) { - fFieldTable.push_back(make_pair(name, MemoryDesc(fFieldIndex++, - getStructSize(), - getStructIntSize(), - getStructRealSize(), - array_typed->fSize, - array_typed->getSizeBytes(), - type, - false, false, - MemoryDesc::kExternal))); - + if ((access & Address::kStaticStruct) || isTable(name) || + (fExternalMemory > 0 && array_typed->fSize > fDLThreshold)) { + fFieldTable.push_back( + make_pair(name, MemoryDesc(fFieldIndex++, getStructSize(), getStructIntSize(), + getStructRealSize(), array_typed->fSize, array_typed->getSizeBytes(), + type, false, false, MemoryDesc::kExternal))); + if (type == Typed::kInt32) { fStructIntOffset += array_typed->getSizeBytes(); } else { @@ -341,15 +341,10 @@ struct StructInstVisitor1 : public StructInstVisitor { fExternalMemory -= array_typed->getSizeBytes(); } else { // Keep arrays in local struct memory - fFieldTable.push_back(make_pair(name, MemoryDesc(fFieldIndex++, - getStructSize(), - getStructIntSize(), - getStructRealSize(), - array_typed->fSize, - array_typed->getSizeBytes(), - type, - false, false, - MemoryDesc::kLocal))); + fFieldTable.push_back( + make_pair(name, MemoryDesc(fFieldIndex++, getStructSize(), getStructIntSize(), + getStructRealSize(), array_typed->fSize, array_typed->getSizeBytes(), + type, false, false, MemoryDesc::kLocal))); } } else { // Should never happen... @@ -358,23 +353,16 @@ struct StructInstVisitor1 : public StructInstVisitor { } else { if (is_struct) { // Scalar variable always stay in local struct memory - fFieldTable.push_back(make_pair(name, MemoryDesc(fFieldIndex++, - getStructSize(), - getStructIntSize(), - getStructRealSize(), - 1, - inst->fType->getSizeBytes(), - inst->fType->getType(), - isConst(name), - isControl(name), - MemoryDesc::kLocal))); + fFieldTable.push_back( + make_pair(name, MemoryDesc(fFieldIndex++, getStructSize(), getStructIntSize(), getStructRealSize(), + 1, inst->fType->getSizeBytes(), inst->fType->getType(), isConst(name), + isControl(name), MemoryDesc::kLocal))); } } - + if (inst->fValue) getMemoryDesc(inst->getName()).fWAccessCount++; DispatchVisitor::visit(inst); } - }; #endif diff --git a/compiler/generator/text_instructions.hh b/compiler/generator/text_instructions.hh index 84cef821dc..182029a936 100644 --- a/compiler/generator/text_instructions.hh +++ b/compiler/generator/text_instructions.hh @@ -29,9 +29,9 @@ #include #include -#include "Text.hh" #include "fir_to_fir.hh" #include "instructions.hh" +#include "Text.hh" #include "type_manager.hh" // Base class to textual visitor: C, C++, Cmajor, CSharp, Dlang, JAX, Julia, Rust, wast @@ -210,6 +210,12 @@ class TextInstVisitor : public InstVisitor { */ virtual bool leftArgNeedsParentheses(BinopInst* inst, ValueInst* arg) { + // Without parentheses, '<' after a cast is interpreted as a generic argument + if ((inst->fOpcode == kLT || inst->fOpcode == kLsh) && dynamic_cast(arg) && + gGlobal->gOutputLang == "rust") { + return true; + } + BinopInst* a = dynamic_cast(arg); if (a) { if (gGlobal->gFullParentheses || special(gBinOpTable[inst->fOpcode]->fName)) { diff --git a/compiler/generator/type_manager.hh b/compiler/generator/type_manager.hh index 64dc3e1454..b31e7ff126 100644 --- a/compiler/generator/type_manager.hh +++ b/compiler/generator/type_manager.hh @@ -214,8 +214,8 @@ class RustStringTypeManager : public StringTypeManager { return named_typed->fName + ((ty_str != "") ? (": " + ty_str) : ""); } else if (array_typed) { return (array_typed->fSize == 0) - ? fPtrRef + generateType(array_typed->fType) - : "[" + generateType(array_typed->fType) + ";" + std::to_string(array_typed->fSize) + "]"; + ? fPtrRef + "[" + generateType(array_typed->fType) + "]" + : "[" + generateType(array_typed->fType) + ";" + std::to_string(array_typed->fSize) + "]"; } else { faustassert(false); return ""; diff --git a/compiler/generator/vec_code_container.cpp b/compiler/generator/vec_code_container.cpp index 978abefa63..49caeda4ac 100644 --- a/compiler/generator/vec_code_container.cpp +++ b/compiler/generator/vec_code_container.cpp @@ -99,7 +99,7 @@ BlockInst* VectorCodeContainer::generateDAGLoopVariant0(const string& counter) */ // Generates the loop DAG - generateDAGLoop(loop_code, size_dec); + generateDAGLoop(loop_code, size_dec->load()); // Generates the DAG enclosing loop StoreVarInst* loop_init = index_dec->store(InstBuilder::genInt32NumInst(0)); @@ -138,7 +138,7 @@ BlockInst* VectorCodeContainer::generateDAGLoopVariant0(const string& counter) */ // Generates the loop DAG - generateDAGLoop(then_block, size_dec1); + generateDAGLoop(then_block, size_dec1->load()); block_res->pushBackInst(InstBuilder::genIfInst(if_cond, then_block)); return block_res; @@ -160,9 +160,9 @@ BlockInst* VectorCodeContainer::generateDAGLoopVariant1(const string& counter) generateLocalOutputs(loop_code, index); // Generate : int count = min(32, (fullcount - index)) - ValueInst* init1 = InstBuilder::genLoadFunArgsVar(counter); - ValueInst* init2 = InstBuilder::genSub(init1, loop_dec->load()); - Values min_fun_args; + ValueInst* init1 = InstBuilder::genLoadFunArgsVar(counter); + ValueInst* init2 = InstBuilder::genSub(init1, loop_dec->load()); + Values min_fun_args; min_fun_args.push_back(InstBuilder::genInt32NumInst(gGlobal->gVecSize)); min_fun_args.push_back(init2); ValueInst* init3 = InstBuilder::genFunCallInst("min_i", min_fun_args); @@ -177,7 +177,7 @@ BlockInst* VectorCodeContainer::generateDAGLoopVariant1(const string& counter) */ // Generates the loop DAG - generateDAGLoop(loop_code, size_dec); + generateDAGLoop(loop_code, size_dec->load()); ValueInst* loop_end = InstBuilder::genLessThan(loop_dec->load(), InstBuilder::genLoadFunArgsVar(counter)); StoreVarInst* loop_increment = loop_dec->store(InstBuilder::genAdd(loop_dec->load(), gGlobal->gVecSize)); @@ -193,7 +193,7 @@ void VectorCodeContainer::processFIR(void) // Default FIR to FIR transformations CodeContainer::processFIR(); - // If stack variables take to much room, move them in struct + // If stack variables take too much room, move them in struct // dump2FIR(fComputeBlockInstructions); VariableSizeCounter counter(Address::kStack); generateComputeBlock(&counter); @@ -211,7 +211,7 @@ void VectorCodeContainer::processFIR(void) // Transform stack array variables in struct variables moveStack2Struct(); } else { - // Sort arrays to be at the begining + // Sort arrays to be at the beginning // fComputeBlockInstructions->fCode.sort(sortArrayDeclarations); } diff --git a/compiler/generator/vec_code_container.hh b/compiler/generator/vec_code_container.hh index 5231842968..3528f0877b 100644 --- a/compiler/generator/vec_code_container.hh +++ b/compiler/generator/vec_code_container.hh @@ -32,7 +32,7 @@ class VectorCodeContainer : public virtual CodeContainer { void moveStack2Struct(); // Code generated with -lv 0 option - BlockInst* generateDAGLoopVariant0(const std::string& counter); + virtual BlockInst* generateDAGLoopVariant0(const std::string& counter); // Code generated with -lv 1 option BlockInst* generateDAGLoopVariant1(const std::string& counter); diff --git a/compiler/generator/wss_code_container.cpp b/compiler/generator/wss_code_container.cpp index 136df0f2db..99a770f5ef 100644 --- a/compiler/generator/wss_code_container.cpp +++ b/compiler/generator/wss_code_container.cpp @@ -323,7 +323,7 @@ BlockInst* WSSCodeContainer::generateDAGLoopWSS(lclgraph dag) for (lclset::const_iterator p = dag[l].begin(); p != dag[l].end(); p++, loop_num++) { // Generates a "case" block for each task BlockInst* case_block = InstBuilder::genBlockInst(); - generateDAGLoopAux(*p, case_block, count_dec, loop_num); + generateDAGLoopAux(*p, case_block, count_dec->load(), loop_num); // Add output tasks activation code @@ -408,7 +408,7 @@ BlockInst* WSSCodeContainer::generateDAGLoopWSS(lclgraph dag) if (level.size() == 1) { BlockInst* case_block = InstBuilder::genBlockInst(); - generateDAGLoopAux(*level.begin(), case_block, count_dec, loop_num); + generateDAGLoopAux(*level.begin(), case_block, count_dec->load(), loop_num); case_block->pushBackInst( InstBuilder::genStoreStackVar("tasknum", InstBuilder::genInt32NumInst(LAST_TASK_INDEX))); // Add the "case" block @@ -416,7 +416,7 @@ BlockInst* WSSCodeContainer::generateDAGLoopWSS(lclgraph dag) } else { for (lclset::const_iterator p = level.begin(); p != level.end(); p++, loop_num++) { BlockInst* case_block = InstBuilder::genBlockInst(); - generateDAGLoopAux(*p, case_block, count_dec, loop_num); + generateDAGLoopAux(*p, case_block, count_dec->load(), loop_num); Values fun_args; fun_args.push_back(InstBuilder::genLoadStructVar("fScheduler")); diff --git a/compiler/global.cpp b/compiler/global.cpp index 878f391276..38f83c0155 100644 --- a/compiler/global.cpp +++ b/compiler/global.cpp @@ -478,6 +478,7 @@ void global::reset() gNamespace = ""; gFullParentheses = false; gCheckIntRange = false; + gReprC = false; gNarrowingLimit = 0; gWideningLimit = 0; @@ -1379,7 +1380,9 @@ bool global::processCmdline(int argc, const char* argv[]) } else if (isCmd(argv[i], "-cir", "--check-integer-range")) { gCheckIntRange = true; i += 1; - + } else if (isCmd(argv[i], "-cabi", "-reprc")) { + gReprC = true; + i += 1; } else if (isCmd(argv[i], "-I", "--import-dir") && (i + 1 < argc)) { if ((strstr(argv[i + 1], "http://") != 0) || (strstr(argv[i + 1], "https://") != 0)) { // We want to search user given directories *before* the standard ones, so insert at the beginning @@ -1997,6 +2000,9 @@ static void printHelp() cout << tab << "-mapp --math-approximation simpler/faster versions of 'floor/ceil/fmod/remainder' functions." << endl; + cout << tab + << "-cabi -reprc (Rust) Force dsp struct layout to follow C ABI." + << endl; cout << tab << "-ns --namespace generate C++ or D code in a namespace ." << endl; cout << tab << "-vhdl --vhdl output vhdl file." << endl; diff --git a/compiler/global.hh b/compiler/global.hh index ca83bdb48d..99f1c7c268 100644 --- a/compiler/global.hh +++ b/compiler/global.hh @@ -176,6 +176,7 @@ struct global { bool gClang; // -clang opttion, when compiled with clang/clang++, adds specific #pragma for auto-vectorization bool gFullParentheses; // -fp option, generate less parenthesis in some textual backends: C/C++, Cmajor, Dlang, Rust bool gCheckIntRange; // -cir option, check float to integer range conversion + bool gReprC; // (Rust) Force dsp struct layout to follow C ABI std::string gClassName; // -cn option, name of the generated dsp class, by default 'mydsp' std::string gProcessName; // -pn option, name of the entry point of the Faust program, by default 'process' diff --git a/compiler/libcode.cpp b/compiler/libcode.cpp index 1ad1820a34..774361f31e 100644 --- a/compiler/libcode.cpp +++ b/compiler/libcode.cpp @@ -118,6 +118,7 @@ #ifdef RUST_BUILD #include "rust_code_container.hh" +#include "dag_instructions_compiler_rust.hh" #endif #ifdef TEMPLATE_BUILD @@ -193,9 +194,9 @@ static bool openOutfile() MANDATORY: use ostringstream which is indeed a subclass of ostream (otherwise subtle dynamic_cast related crash can occur...) *******************************************************************/ - + bool res = false; - + if (gGlobal->gOutputFile == "string") { gDst = unique_ptr(new ostringstream()); } else if (gGlobal->gOutputFile == "binary") { @@ -212,7 +213,7 @@ static bool openOutfile() } else { gDst = std::move(fdst); } - + } else { gDst = unique_ptr(new ostringstream()); res = true; @@ -475,7 +476,8 @@ static void compileRust(Tree signals, int numInputs, int numOutputs, ostream* ou gContainer = RustCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out); if (gGlobal->gVectorSwitch) { - gNewComp = new DAGInstructionsCompiler(gContainer); + // gNewComp = new DAGInstructionsCompiler(gContainer); + gNewComp = new DAGInstructionsCompilerRust(gContainer); } else { gNewComp = new InstructionsCompiler1(gContainer); } @@ -788,7 +790,7 @@ static void generateCodeAux1(unique_ptr& helpers, unique_ptr& if (gGlobal->gNamespace != "" && gGlobal->gOutputLang == "cpp") { *dst.get() << "} // namespace " << gGlobal->gNamespace << endl; } - + } else { gContainer->printHeader(); gContainer->printFloatDef(); @@ -1156,12 +1158,12 @@ static void* createFactoryAux1(void* arg) gGlobal->printDirectories(); faust_alarm(gGlobal->gTimeout); - + // Open output file bool is_cout = openOutfile(); // Open enrobage file openEnrobagefile(); - + /**************************************************************** 1.5 - Check and open some input files *****************************************************************/ @@ -1280,10 +1282,10 @@ static void* createFactoryAux2(void* arg) gGlobal->initDocumentNames(); initFaustFloat(); - + // Open output file openOutfile(); - + /************************************************************************* 5 - preparation of the signal tree and translate output signals **************************************************************************/ diff --git a/compiler/parallelize/code_loop.cpp b/compiler/parallelize/code_loop.cpp index fc528d82cf..112050c648 100644 --- a/compiler/parallelize/code_loop.cpp +++ b/compiler/parallelize/code_loop.cpp @@ -100,7 +100,7 @@ BlockInst* CodeLoop::generateOneSample() return static_cast(block->clone(&cloner)); } -void CodeLoop::generateDAGScalarLoop(BlockInst* block, DeclareVarInst* count, bool omp) +void CodeLoop::generateDAGScalarLoop(BlockInst* block, LoadVarInst* count, bool omp) { // Generate code for extra loops for (list::const_iterator s = fExtraLoops.begin(); s != fExtraLoops.end(); s++) { @@ -120,7 +120,7 @@ void CodeLoop::generateDAGScalarLoop(BlockInst* block, DeclareVarInst* count, bo if (fComputeInst->fCode.size() > 0) { DeclareVarInst* loop_decl = InstBuilder::genDecLoopVar(fLoopIndex, InstBuilder::genInt32Typed(), InstBuilder::genInt32NumInst(0)); - ValueInst* loop_end = InstBuilder::genLessThan(loop_decl->load(), count->load()); + ValueInst* loop_end = InstBuilder::genLessThan(loop_decl->load(), count); StoreVarInst* loop_increment = loop_decl->store(InstBuilder::genAdd(loop_decl->load(), 1)); block->pushBackInst(InstBuilder::genLabelInst("/* Compute code */")); diff --git a/compiler/parallelize/code_loop.hh b/compiler/parallelize/code_loop.hh index 69addc5445..85e10092ed 100644 --- a/compiler/parallelize/code_loop.hh +++ b/compiler/parallelize/code_loop.hh @@ -166,7 +166,7 @@ class CodeLoop : public virtual Garbageable { BlockInst* generateOneSample(); - void generateDAGScalarLoop(BlockInst* block, DeclareVarInst* count, bool omp); + void generateDAGScalarLoop(BlockInst* block, LoadVarInst* count, bool omp); void transform(DispatchVisitor* visitor) { diff --git a/tests/impulse-tests/Makefile b/tests/impulse-tests/Makefile index cf089edb74..44129cc677 100644 --- a/tests/impulse-tests/Makefile +++ b/tests/impulse-tests/Makefile @@ -359,6 +359,8 @@ interp1: rust: $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double" $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double -fp" + $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double -vec -vs 4" + $(MAKE) -f Make.rust FAUSTOPTIONS="-I dsp -double -vec -vs 32" ######################################################################### # Cmajor backend diff --git a/tests/impulse-tests/archs/rust/Cargo.toml b/tests/impulse-tests/archs/rust/Cargo.toml index 7181516105..ba2ebd9770 100644 --- a/tests/impulse-tests/archs/rust/Cargo.toml +++ b/tests/impulse-tests/archs/rust/Cargo.toml @@ -7,3 +7,8 @@ edition = "2018" libm = "*" num-traits = "*" +default-boxed = "0.2" + +[features] +default = ["default-boxed"] +default-boxed = [] diff --git a/tests/impulse-tests/archs/rust/architecture.rs b/tests/impulse-tests/archs/rust/architecture.rs index 818c322adc..63d9a49db1 100644 --- a/tests/impulse-tests/archs/rust/architecture.rs +++ b/tests/impulse-tests/archs/rust/architecture.rs @@ -223,7 +223,8 @@ fn run_dsp(mut dsp: Box, num_samples: usize, line_num_offset: usize, outp } fn new_dsp() -> Box { - Box::new(mydsp::new()) + use default_boxed::DefaultBoxed; + mydsp::default_boxed() } fn main() {