Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

CI: Check format using scalafmt #33

Merged
merged 2 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ jobs:
run: sbt tests/test
- name: Run the Sample
run: sbt sample/run
- name: Format
run: sbt scalafmtCheckAll
1 change: 1 addition & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
version = "3.7.15"
runner.dialect = scala213
maxColumn = 100
literals.hexDigits = "Upper"
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")
2 changes: 1 addition & 1 deletion wasm/src/main/scala/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object Main {
val builder = new WasmBuilder()
implicit val context: WasmContext = new WasmContext(module)
basicTestClassDefs.foreach { clazz =>
//builder.transformClassDef(clazz)
// builder.transformClassDef(clazz)
???
}
val writer = new converters.WasmTextWriter()
Expand Down
13 changes: 8 additions & 5 deletions wasm/src/main/scala/converters/WasmBinaryWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,13 @@ final class WasmBinaryWriter(module: WasmModule) {

private def writeInstr(buf: Buffer, instr: WasmInstr): Unit = {
val opcode = instr.opcode
if (opcode <= 0xff) {
if (opcode <= 0xFF) {
buf.byte(opcode.toByte)
} else {
assert(opcode <= 0xffff, s"cannot encode an opcode longer than 2 bytes yet: ${opcode.toHexString}")
assert(
opcode <= 0xFFFF,
s"cannot encode an opcode longer than 2 bytes yet: ${opcode.toHexString}"
)
buf.byte((opcode >>> 8).toByte)
buf.byte(opcode.toByte)
}
Expand Down Expand Up @@ -313,7 +316,7 @@ object WasmBinaryWriter {
def result(): Array[Byte] = buf.toByteArray()

def byte(b: Byte): Unit =
buf.write(b & 0xff)
buf.write(b & 0xFF)

def rawByteArray(array: Array[Byte]): Unit =
buf.write(array)
Expand Down Expand Up @@ -390,14 +393,14 @@ object WasmBinaryWriter {
if (next == 0) {
buf.write(value.toInt)
} else {
buf.write((value.toInt & 0x7f) | 0x80)
buf.write((value.toInt & 0x7F) | 0x80)
unsignedLEB128(next)
}
}

@tailrec
private def signedLEB128(value: Long): Unit = {
val chunk = value.toInt & 0x7f
val chunk = value.toInt & 0x7F
val next = value >> 7
if (next == (if ((chunk & 0x40) != 0) -1 else 0)) {
buf.write(chunk)
Expand Down
44 changes: 27 additions & 17 deletions wasm/src/main/scala/converters/WasmTextWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,27 @@ class WasmTextWriter {
)

private def writeImport(i: WasmImport)(implicit b: WatBuilder): Unit = {
b.newLineList("import", {
b.appendElement(s"\"${i.module}\"")
b.appendElement(s"\"${i.name}\"")
b.newLineList(
"import", {
b.appendElement(s"\"${i.module}\"")
b.appendElement(s"\"${i.name}\"")

i.desc match {
case WasmImportDesc.Func(id, typ) =>
b.sameLineList(
"func", {
b.appendElement(id.show)
writeSig(typ.params, typ.results)
}
)
i.desc match {
case WasmImportDesc.Func(id, typ) =>
b.sameLineList(
"func", {
b.appendElement(id.show)
writeSig(typ.params, typ.results)
}
)
}
}
})
)
}

private def writeSig(params: List[WasmType], results: List[WasmType])(implicit b: WatBuilder): Unit = {
private def writeSig(params: List[WasmType], results: List[WasmType])(implicit
b: WatBuilder
): Unit = {
params.foreach(typ => b.sameLineListOne("param", typ.show))
results.foreach(typ => b.sameLineListOne("result", typ.show))
}
Expand Down Expand Up @@ -256,15 +260,19 @@ class WasmTextWriter {
case WasmImmediate.LabelIdxVector(indices) =>
indices.map(i => "$" + i.value).mkString(" ")
case i: WasmImmediate.CastFlags =>
throw new UnsupportedOperationException(s"CastFlags $i must be handled directly in the instruction $instr")
throw new UnsupportedOperationException(
s"CastFlags $i must be handled directly in the instruction $instr"
)
case _ =>
println(i)
???
}
b.appendElement(str)
}

private def writeRefTypeImmediate(i: WasmImmediate.HeapType, nullable: Boolean)(implicit b: WatBuilder): Unit = {
private def writeRefTypeImmediate(i: WasmImmediate.HeapType, nullable: Boolean)(implicit
b: WatBuilder
): Unit = {
if (nullable)
b.appendElement(s"(ref null ${i.value.show})")
else
Expand All @@ -286,8 +294,10 @@ class WasmTextWriter {
}

def writeBrOnCastImmediates(
castFlags: WasmImmediate.CastFlags, label: WasmImmediate.LabelIdx,
from: WasmImmediate.HeapType, to: WasmImmediate.HeapType
castFlags: WasmImmediate.CastFlags,
label: WasmImmediate.LabelIdx,
from: WasmImmediate.HeapType,
to: WasmImmediate.HeapType
): Unit = {
writeImmediate(label, instr)
writeRefTypeImmediate(from, castFlags.nullable1)
Expand Down
138 changes: 82 additions & 56 deletions wasm/src/main/scala/ir2wasm/HelperFunctions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,16 @@ object HelperFunctions {
}

/** `typeDataName: (ref typeData) -> (ref any)` (representing a `string`).
*
* Initializes the `name` field of the given `typeData` if that was not done
* yet, and returns its value.
*
* The computed value is specified by `java.lang.Class.getName()`. See also
* the documentation on [[Names.WasmFieldName.typeData.name]] for details.
*
* @see [[https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html#getName()]]
*/
*
* Initializes the `name` field of the given `typeData` if that was not done yet, and returns its
* value.
*
* The computed value is specified by `java.lang.Class.getName()`. See also the documentation on
* [[Names.WasmFieldName.typeData.name]] for details.
*
* @see
* [[https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html#getName()]]
*/
private def genTypeDataName()(implicit ctx: WasmContext): Unit = {
import WasmImmediate._
import WasmTypeName._
Expand Down Expand Up @@ -149,7 +150,10 @@ object HelperFunctions {

// componentTypeData := ref_as_non_null(typeData.componentType)
instrs += LOCAL_GET(typeDataParam)
instrs += STRUCT_GET(TypeIdx(WasmStructTypeName.typeData), WasmFieldName.typeData.componentTypeIdx)
instrs += STRUCT_GET(
TypeIdx(WasmStructTypeName.typeData),
WasmFieldName.typeData.componentTypeIdx
)
instrs += REF_AS_NOT_NULL
instrs += LOCAL_TEE(componentTypeDataLocal)

Expand All @@ -162,7 +166,10 @@ object HelperFunctions {

// componentNameData := componentTypeData.nameData
instrs += LOCAL_GET(componentTypeDataLocal)
instrs += STRUCT_GET(TypeIdx(WasmStructTypeName.typeData), WasmFieldName.typeData.nameDataIdx)
instrs += STRUCT_GET(
TypeIdx(WasmStructTypeName.typeData),
WasmFieldName.typeData.nameDataIdx
)
instrs += REF_AS_NOT_NULL
instrs += LOCAL_TEE(componentNameDataLocal)

Expand Down Expand Up @@ -239,7 +246,10 @@ object HelperFunctions {
} {
// it is not an array; its name is stored in nameData
instrs += LOCAL_GET(typeDataParam)
instrs += STRUCT_GET(TypeIdx(WasmStructTypeName.typeData), WasmFieldName.typeData.nameDataIdx)
instrs += STRUCT_GET(
TypeIdx(WasmStructTypeName.typeData),
WasmFieldName.typeData.nameDataIdx
)
instrs += REF_AS_NOT_NULL
instrs += CALL(FuncIdx(WasmFunctionName.createStringFromData))
}
Expand All @@ -254,13 +264,13 @@ object HelperFunctions {
}

/** `createClassOf: (ref typeData) -> (ref jlClass)`.
*
* Creates the unique `java.lang.Class` instance associated with the given
* `typeData`, stores it in its `classOfValue` field, and returns it.
*
* Must be called only if the `classOfValue` of the typeData is null. All
* call sites must deal with the non-null case as a fast-path.
*/
*
* Creates the unique `java.lang.Class` instance associated with the given `typeData`, stores it
* in its `classOfValue` field, and returns it.
*
* Must be called only if the `classOfValue` of the typeData is null. All call sites must deal
* with the non-null case as a fast-path.
*/
private def genCreateClassOf()(implicit ctx: WasmContext): Unit = {
import WasmImmediate._
import WasmTypeName.WasmStructTypeName
Expand Down Expand Up @@ -327,11 +337,15 @@ object HelperFunctions {
// TODO: "isInstance", "isAssignableFrom", "checkCast", "newArrayOfThisClass"

// Call java.lang.Class::<init>(dataObject)
instrs += CALL(FuncIdx(WasmFunctionName(
IRTrees.MemberNamespace.Constructor,
IRNames.ClassClass,
SpecialNames.ClassCtor
)))
instrs += CALL(
FuncIdx(
WasmFunctionName(
IRTrees.MemberNamespace.Constructor,
IRNames.ClassClass,
SpecialNames.ClassCtor
)
)
)

// typeData.classOf := classInstance
instrs += LOCAL_GET(typeDataParam)
Expand All @@ -345,13 +359,13 @@ object HelperFunctions {
}

/** `getClassOf: (ref typeData) -> (ref jlClass)`.
*
* Initializes the `java.lang.Class` instance associated with the given
* `typeData` if not already done, and returns it.
*
* This includes the fast-path and the slow-path to `createClassOf`, for
* call sites that are not performance-sensitive.
*/
*
* Initializes the `java.lang.Class` instance associated with the given `typeData` if not already
* done, and returns it.
*
* This includes the fast-path and the slow-path to `createClassOf`, for call sites that are not
* performance-sensitive.
*/
private def genGetClassOf()(implicit ctx: WasmContext): Unit = {
import WasmImmediate._
import WasmTypeName.WasmStructTypeName
Expand Down Expand Up @@ -382,10 +396,9 @@ object HelperFunctions {
}

/** `arrayTypeData: (ref typeData), i32 -> (ref typeData)`.
*
* Returns the typeData of an array with `dims` dimensions over the given
* typeData.
*/
*
* Returns the typeData of an array with `dims` dimensions over the given typeData.
*/
private def genArrayTypeData()(implicit ctx: WasmContext): Unit = {
import WasmImmediate._
import WasmTypeName.WasmStructTypeName
Expand Down Expand Up @@ -421,7 +434,10 @@ object HelperFunctions {
fctx.block(typeDataType) { arrayOfIsNonNullLabel =>
// br_on_non_null $arrayOfIsNonNull typeData.arrayOf
instrs += LOCAL_GET(typeDataParam)
instrs += STRUCT_GET(TypeIdx(WasmStructTypeName.typeData), WasmFieldName.typeData.arrayOfIdx)
instrs += STRUCT_GET(
TypeIdx(WasmStructTypeName.typeData),
WasmFieldName.typeData.arrayOfIdx
)
instrs += BR_ON_NON_NULL(arrayOfIsNonNullLabel)

// <top-of-stack> := typeData ; for the <old typeData>.arrayOf := ... later on
Expand All @@ -438,7 +454,10 @@ object HelperFunctions {
instrs += LOCAL_TEE(typeDataParam)

// <old typeData>.arrayOf := typeData
instrs += STRUCT_SET(TypeIdx(WasmStructTypeName.typeData), WasmFieldName.typeData.arrayOfIdx)
instrs += STRUCT_SET(
TypeIdx(WasmStructTypeName.typeData),
WasmFieldName.typeData.arrayOfIdx
)

// loop back to the beginning
instrs += BR(loopLabel)
Expand All @@ -454,10 +473,9 @@ object HelperFunctions {
}

/** `getComponentType: (ref typeData) -> (ref null jlClass)`.
*
* This is the underlying func for the `getComponentType()` closure inside
* class data objects.
*/
*
* This is the underlying func for the `getComponentType()` closure inside class data objects.
*/
private def genGetComponentType()(implicit ctx: WasmContext): Unit = {
import WasmImmediate._
import WasmTypeName.WasmStructTypeName
Expand All @@ -479,7 +497,10 @@ object HelperFunctions {
fctx.block() { nullResultLabel =>
// Try and extract non-null component type data
instrs += LOCAL_GET(typeDataParam)
instrs += STRUCT_GET(TypeIdx(WasmStructTypeName.typeData), WasmFieldName.typeData.componentTypeIdx)
instrs += STRUCT_GET(
TypeIdx(WasmStructTypeName.typeData),
WasmFieldName.typeData.componentTypeIdx
)
instrs += BR_ON_NULL(nullResultLabel)
// Get the corresponding classOf
instrs += CALL(FuncIdx(WasmFunctionName.getClassOf))
Expand All @@ -491,13 +512,13 @@ object HelperFunctions {
}

/** `anyGetClass: (ref any) -> (ref null jlClass)`.
*
* This is the implementation of `value.getClass()` when `value` can be an
* instance of a hijacked class, i.e., a primitive.
*
* For `number`s, the result is based on the actual value, as specified by
* [[https://www.scala-js.org/doc/semantics.html#getclass]].
*/
*
* This is the implementation of `value.getClass()` when `value` can be an instance of a hijacked
* class, i.e., a primitive.
*
* For `number`s, the result is based on the actual value, as specified by
* [[https://www.scala-js.org/doc/semantics.html#getclass]].
*/
private def genAnyGetClass()(implicit ctx: WasmContext): Unit = {
import WasmImmediate._
import WasmTypeName.WasmStructTypeName
Expand Down Expand Up @@ -542,13 +563,18 @@ object HelperFunctions {
fctx.block() { typeBooleanLabel =>
instrs += LOCAL_GET(valueParam)
instrs += CALL(FuncIdx(WasmFunctionName.jsValueType))
instrs += BR_TABLE(LabelIdxVector(List(
typeBooleanLabel, // 0
typeBooleanLabel, // 1
typeStringLabel, // 2
typeNumberLabel, // 3
typeUndefinedLabel, // 4
)), typeOtherLabel)
instrs += BR_TABLE(
LabelIdxVector(
List(
typeBooleanLabel, // 0
typeBooleanLabel, // 1
typeStringLabel, // 2
typeNumberLabel, // 3
typeUndefinedLabel // 4
)
),
typeOtherLabel
)
}

// typeBoolean:
Expand Down
Loading