Skip to content

Commit

Permalink
Add support for alignment attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
densh committed May 8, 2017
1 parent 9a044ba commit 206f28e
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 22 deletions.
10 changes: 8 additions & 2 deletions nir/src/main/scala/scala/scalanative/nir/Attrs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ object Attr {
final case object Extern extends Attr
final case class Override(name: Global) extends Attr

final case class Align(value: Int) extends Attr

// Linker attributes
final case class Link(name: String) extends Attr
sealed abstract class Pin extends Attr
Expand All @@ -35,7 +37,8 @@ final case class Attrs(inline: Inline = MayInline,
isDyn: Boolean = false,
overrides: Seq[Global] = Seq(),
pins: Seq[Pin] = Seq(),
links: Seq[Attr.Link] = Seq()) {
links: Seq[Attr.Link] = Seq(),
align: Option[Int] = scala.None) {
def toSeq: Seq[Attr] = {
val out = mutable.UnrolledBuffer.empty[Attr]

Expand All @@ -46,6 +49,7 @@ final case class Attrs(inline: Inline = MayInline,
overrides.foreach { out += Override(_) }
out ++= pins
out ++= links
align.foreach { out += Align(_) }

out
}
Expand All @@ -58,6 +62,7 @@ object Attrs {
var isPure = false
var isExtern = false
var isDyn = false
var align = Option.empty[Int]
val overrides = mutable.UnrolledBuffer.empty[Global]
val pins = mutable.UnrolledBuffer.empty[Pin]
val links = mutable.UnrolledBuffer.empty[Attr.Link]
Expand All @@ -67,11 +72,12 @@ object Attrs {
case Pure => isPure = true
case Extern => isExtern = true
case Dyn => isDyn = true
case Align(value) => align = Some(value)
case Override(name) => overrides += name
case attr: Pin => pins += attr
case link: Attr.Link => links += link
}

new Attrs(inline, isPure, isExtern, isDyn, overrides, pins, links)
new Attrs(inline, isPure, isExtern, isDyn, overrides, pins, links, align)
}
}
4 changes: 4 additions & 0 deletions nir/src/main/scala/scala/scalanative/nir/Show.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ object Show {
str("alwaysinline")
case Attr.Dyn =>
str("dyn")
case Attr.Align(value) =>
str("align(")
str(value)
str(")")
case Attr.Pure =>
str("pure")
case Attr.Extern =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import nir.serialization.{Tags => T}
final class BinarySerializer(buffer: ByteBuffer) {
import buffer._

// Things to change in next binary-breaking release:
// 1. Val.Null should have its own tag, not encoded via Val.Zero(Type.Ptr).
// 2. Volatile Op.{Load, Store} should become serializable.
// 3. Attr.Align should become serializable;

final def serialize(defns: Seq[Defn]): Unit = {
val names = defns.map(_.name)
val positions = mutable.UnrolledBuffer.empty[Int]
Expand Down Expand Up @@ -67,6 +72,9 @@ final class BinarySerializer(buffer: ByteBuffer) {

case Attr.Dyn => putInt(T.DynAttr)

case Attr.Align(_) =>
assert(false, "alignment attribute is not serializable")

case Attr.Pure => putInt(T.PureAttr)
case Attr.Extern => putInt(T.ExternAttr)
case Attr.Override(n) => putInt(T.OverrideAttr); putGlobal(n)
Expand Down Expand Up @@ -265,13 +273,13 @@ final class BinarySerializer(buffer: ByteBuffer) {
putNext(unwind)

case Op.Load(ty, ptr, isVolatile) =>
assert(!isVolatile, "nir binary format doesn't support volatile loads")
assert(!isVolatile, "volatile loads are not serializable")
putInt(T.LoadOp)
putType(ty)
putVal(ptr)

case Op.Store(ty, value, ptr, isVolatile) =>
assert(!isVolatile, "nir binary format doesn't support volatile stores")
assert(!isVolatile, "volatile stores are not serializable")
putInt(T.StoreOp)
putType(ty)
putVal(value)
Expand Down
14 changes: 9 additions & 5 deletions tools/src/main/scala/scala/scalanative/codegen/CodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ object CodeGen {
case Defn.Struct(attrs, name, tys) =>
genStruct(attrs, name, tys)
case Defn.Var(attrs, name, ty, rhs) =>
genGlobalDefn(name, attrs.isExtern, isConst = false, ty, rhs)
genGlobalDefn(attrs, name, isConst = false, ty, rhs)
case Defn.Const(attrs, name, ty, rhs) =>
genGlobalDefn(name, attrs.isExtern, isConst = true, ty, rhs)
genGlobalDefn(attrs, name, isConst = true, ty, rhs)
case Defn.Declare(attrs, name, sig) =>
genFunctionDefn(attrs, name, sig, Seq())
case Defn.Define(attrs, name, sig, blocks) =>
Expand All @@ -175,21 +175,25 @@ object CodeGen {
str("}")
}

def genGlobalDefn(name: nir.Global,
isExtern: Boolean,
def genGlobalDefn(attrs: Attrs,
name: nir.Global,
isConst: Boolean,
ty: nir.Type,
rhs: nir.Val): Unit = {
str("@")
genGlobal(name)
str(" = ")
str(if (isExtern) "external " else "")
str(if (attrs.isExtern) "external " else "")
str(if (isConst) "constant" else "global")
str(" ")
rhs match {
case Val.None => genType(ty)
case rhs => genVal(rhs)
}
attrs.align.foreach { value =>
str(", align ")
str(value)
}
}

def genFunctionDefn(attrs: Attrs,
Expand Down
5 changes: 4 additions & 1 deletion tools/src/main/scala/scala/scalanative/nir/parser/Attr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ object Attr extends Base[nir.Attr] {
val InlineHint = P("inlinehint".! map (_ => nir.Attr.InlineHint))
val NoInline = P("noinline".! map (_ => nir.Attr.NoInline))
val AlwaysInline = P("alwaysinline".! map (_ => nir.Attr.AlwaysInline))
val Dyn = P("dyn".! map (_ => nir.Attr.Dyn))
val Align = P(("align(" ~ int ~ ")") map (nir.Attr.Align(_)))
val Pure = P("pure".! map (_ => nir.Attr.Pure))
val Extern = P("extern".! map (_ => nir.Attr.Extern))
val Override =
Expand All @@ -23,8 +25,9 @@ object Attr extends Base[nir.Attr] {
P("pin-if(" ~ Global.parser ~ "," ~ Global.parser ~ ")" map {
case (name, cond) => nir.Attr.PinIf(name, cond)
})
val PinWeak = P("pin-weak(" ~ Global.parser ~ ")" map (nir.Attr.PinWeak(_)))

override val parser: P[nir.Attr] =
MayInline | InlineHint | NoInline | AlwaysInline | Pure | Extern | Override | Link | PinAlways | PinIf
MayInline | InlineHint | NoInline | AlwaysInline | Dyn | Align | Pure | Extern | Override | Link | PinAlways | PinIf | PinWeak

}
6 changes: 4 additions & 2 deletions tools/src/main/scala/scala/scalanative/optimizer/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ object Driver {
inject.RuntimeTypeInformation,
inject.ClassStruct,
inject.ObjectArrayId,
inject.ModuleArray
inject.ModuleArray,
inject.SafepointTrigger
)

private val fastOptPasses = Seq(
Expand Down Expand Up @@ -60,7 +61,8 @@ object Driver {
pass.AllocLowering,
pass.SizeofLowering,
pass.CopyPropagation,
pass.DeadCodeElimination
pass.DeadCodeElimination,
pass.SafepointInsertion
)

/** Create driver with default pipeline for this configuration. */
Expand Down
25 changes: 15 additions & 10 deletions tools/src/test/scala/scala/scalanative/nir/AttrParserTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,21 @@ class AttrParserTest extends FlatSpec with Matchers {

"The NIR parser" should "parse attributes" in {
import Attr._
val attrs: Seq[Attr] = Seq(MayInline,
InlineHint,
NoInline,
AlwaysInline,
Pure,
Extern,
Override(global),
Link("test"),
PinAlways(global),
PinIf(global, global))
val attrs: Seq[Attr] = Seq(
MayInline,
InlineHint,
NoInline,
AlwaysInline,
Dyn,
Align(1024),
Pure,
Extern,
Override(global),
Link("test"),
PinAlways(global),
PinIf(global, global),
PinWeak(global)
)

attrs foreach { attr =>
val Parsed.Success(result, _) = parser.Attr.parser.parse(attr.show)
Expand Down

0 comments on commit 206f28e

Please sign in to comment.