diff options
Diffstat (limited to 'macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala')
| -rw-r--r-- | macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala new file mode 100644 index 00000000..6d7c3411 --- /dev/null +++ b/macros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala @@ -0,0 +1,186 @@ +// See LICENSE for license details. + +// This file transform macro definitions to explicitly add implicit source info to Chisel method +// calls. + +package chisel3.internal.sourceinfo + +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context +import scala.reflect.macros.whitebox + + +/** Transforms a function call so that it can both provide implicit-style source information and + * have a chained apply call. Without macros, only one is possible, since having a implicit + * argument in the definition will cause the compiler to interpret a chained apply as an + * explicit implicit argument and give type errors. + * + * Instead of an implicit argument, the public-facing function no longer takes a SourceInfo at all. + * The macro transforms the public-facing function into a call to an internal function that takes + * an explicit SourceInfo by inserting an implicitly[SourceInfo] as the explicit argument. + */ +trait SourceInfoTransformMacro { + val c: Context + import c.universe._ + def thisObj: Tree = c.prefix.tree + def implicitSourceInfo = q"implicitly[_root_.chisel3.internal.sourceinfo.SourceInfo]" + def implicitCompileOptions = q"implicitly[_root_.chisel3.CompileOptions]" +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object UIntTransform +class UIntTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def bitset(off: c.Tree, dat: c.Tree): c.Tree = { + q"$thisObj.do_bitSet($off, $dat)($implicitSourceInfo, $implicitCompileOptions)" + } +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object InstTransform +// Module instantiation transform +class InstTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](bc: c.Tree): c.Tree = { + q"$thisObj.do_apply($bc)($implicitSourceInfo, $implicitCompileOptions)" + } +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object MemTransform +class MemTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree): c.Tree = { + q"$thisObj.do_apply($size, $t)($implicitSourceInfo, $implicitCompileOptions)" + } + def apply_ruw[T: c.WeakTypeTag](size: c.Tree, t: c.Tree, ruw: c.Tree): c.Tree = { + q"$thisObj.do_apply($size, $t, $ruw)($implicitSourceInfo, $implicitCompileOptions)" + } +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object MuxTransform +class MuxTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](cond: c.Tree, con: c.Tree, alt: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply[$tpe]($cond, $con, $alt)($implicitSourceInfo, $implicitCompileOptions)" + } +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object VecTransform +class VecTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply_elts(elts: c.Tree): c.Tree = { + q"$thisObj.do_apply($elts)($implicitSourceInfo, $implicitCompileOptions)" + } + def apply_elt0(elt0: c.Tree, elts: c.Tree*): c.Tree = { + q"$thisObj.do_apply($elt0, ..$elts)($implicitSourceInfo, $implicitCompileOptions)" + } + def tabulate(n: c.Tree)(gen: c.Tree): c.Tree = { + q"$thisObj.do_tabulate($n)($gen)($implicitSourceInfo, $implicitCompileOptions)" + } + def fill(n: c.Tree)(gen: c.Tree): c.Tree = { + q"$thisObj.do_fill($n)($gen)($implicitSourceInfo, $implicitCompileOptions)" + } + def contains(x: c.Tree)(ev: c.Tree): c.Tree = { + q"$thisObj.do_contains($x)($implicitSourceInfo, $ev, $implicitCompileOptions)" + } + def reduceTree(redOp: c.Tree, layerOp: c.Tree): c.Tree = { + q"$thisObj.do_reduceTree($redOp,$layerOp)($implicitSourceInfo, $implicitCompileOptions)" + } + def reduceTreeDefault(redOp: c.Tree ): c.Tree = { + q"$thisObj.do_reduceTree($redOp)($implicitSourceInfo, $implicitCompileOptions)" + } +} + +/** "Automatic" source information transform / insertion macros, which generate the function name + * based on the macro invocation (instead of explicitly writing out every transform). + */ +abstract class AutoSourceTransform extends SourceInfoTransformMacro { + import c.universe._ + /** Returns the TermName of the transformed function, which is the applied function name with do_ + * prepended. + */ + def doFuncTerm: TermName = { + val funcName = c.macroApplication match { + case q"$_.$funcName[..$_](...$_)" => funcName + case _ => throw new Exception(s"Chisel Internal Error: Could not resolve function name from macro application: ${showCode(c.macroApplication)}") // scalastyle:ignore line.size.limit + } + TermName("do_" + funcName) + } +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object SourceInfoTransform +class SourceInfoTransform(val c: Context) extends AutoSourceTransform { + import c.universe._ + + def noArg(): c.Tree = { + q"$thisObj.$doFuncTerm($implicitSourceInfo, $implicitCompileOptions)" + } + + def thatArg(that: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($that)($implicitSourceInfo, $implicitCompileOptions)" + } + + def nArg(n: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($n)($implicitSourceInfo, $implicitCompileOptions)" + } + + def pArg(p: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($p)($implicitSourceInfo, $implicitCompileOptions)" + } + + def inArg(in: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($in)($implicitSourceInfo, $implicitCompileOptions)" + } + + def xArg(x: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($x)($implicitSourceInfo, $implicitCompileOptions)" + } + + def xyArg(x: c.Tree, y: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($x, $y)($implicitSourceInfo, $implicitCompileOptions)" + } + + def xEnArg(x: c.Tree, en: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($x, $en)($implicitSourceInfo, $implicitCompileOptions)" + } +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object CompileOptionsTransform +class CompileOptionsTransform(val c: Context) extends AutoSourceTransform { + import c.universe._ + + def thatArg(that: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($that)($implicitCompileOptions)" + } + + def inArg(in: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($in)($implicitCompileOptions)" + } + + def pArg(p: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($p)($implicitCompileOptions)" + } +} + +// Workaround for https://github.com/sbt/sbt/issues/3966 +object SourceInfoWhiteboxTransform +/** Special whitebox version of the blackbox SourceInfoTransform, used when fun things need to + * happen to satisfy the type system while preventing the use of macro overrides. + */ +class SourceInfoWhiteboxTransform(val c: whitebox.Context) extends AutoSourceTransform { + import c.universe._ + + def noArg(): c.Tree = { + q"$thisObj.$doFuncTerm($implicitSourceInfo, $implicitCompileOptions)" + } + + def thatArg(that: c.Tree): c.Tree = { + q"$thisObj.$doFuncTerm($that)($implicitSourceInfo, $implicitCompileOptions)" + } +} |
