Skip to content

Commit 1ef827b

Browse files
committed
Merge branch 'llvm' of github.com:greedy/scala into llvm
2 parents d67c560 + 2b30d28 commit 1ef827b

File tree

5 files changed

+105
-23
lines changed

5 files changed

+105
-23
lines changed

docs/examples/llvm/runtime.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ package java {
195195
def toString(i: scala.Int) = valueOf(i).toString
196196

197197
def rotateLeft(i: scala.Int, amt: scala.Int) = (i << (32-amt)) | (i >>> amt)
198+
def signum(i: scala.Int) = if (i < 0) -1 else if (i == 0) 0 else 1
198199
}
199200
class Integer(value: scala.Int) extends Number {
200201
// def byteValue: scala.Byte = value.toByte
@@ -277,6 +278,7 @@ package java {
277278
def toHexString(i: scala.Long): java.lang.String = sys.error("unimplemented")
278279
def toOctalString(i: scala.Long): java.lang.String = sys.error("unimplemented")
279280
def toString(i: scala.Long) = valueOf(i).toString
281+
def signum(l: scala.Long) = if (l < 0) -1 else if (l == 0) 0 else 1
280282
}
281283
class Long(value: scala.Long) extends Number {
282284
// def byteValue: scala.Byte = value.toByte

src/compiler/scala/tools/nsc/backend/llvm/GenLLVM.scala

Lines changed: 92 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,14 @@ abstract class GenLLVM extends SubComponent {
681681
}
682682
}
683683

684+
def externFieldFun(s: Symbol, static: Boolean) = {
685+
externFuns.getOrElseUpdate(s, {
686+
val fun = fieldPtrfun(s, static)
687+
fun.tpe.argTypes.foreach(recordType)
688+
recordType(fun.tpe.returnType)
689+
fun
690+
})
691+
}
684692
def externFun(s: Symbol) = {
685693
externFuns.getOrElseUpdate(s, {
686694
val fun = functionForMethodSymbol(s)
@@ -717,12 +725,23 @@ abstract class GenLLVM extends SubComponent {
717725

718726
val virtualMethodCache: mutable.Map[Symbol,List[Symbol]] = new mutable.HashMap
719727

728+
729+
/* intp("scala.Some").info.decls.toList filterNot (_.allOverriddenSymbols.headOption exists (_ isDeferred)) */
730+
/*
731+
def vms(s:Symbol):List[(Symbol,List[Symbol])] = if (s == NoSymbol) Nil else { val sms = vms(s.superClass); val mms = s.info.members.filterNot(m => !m.isMethod || m.isConstructor || m.isEffectivelyFinal || m.isOverride || m.allOverriddenSymbols.exists(o => supers(s).contains(o.owner))); sms ++ List((s,(mms.toSet -- sms.flatMap(_._2).toSet).toList)) }
732+
*/
720733
def virtualMethods(s: Symbol): List[Symbol] = {
721734
virtualMethodCache.getOrElseUpdate(s,
722735
if (s == NoSymbol) Nil
723736
else {
724-
val myvirts = s.info.decls.toList.filter(d => d.isMethod && !d.isConstructor && !(d.isOverride && s.superClass.info.members.exists(mem => mem.info <:< d.info && mem.name == d.name)) && (d.isDeferred || !d.isEffectivelyFinal))
737+
val supers = Stream.iterate(s.superClass)(_.superClass).takeWhile(s => s != NoSymbol).toList
738+
val mymembers = s.info.members.filterNot(m => !m.isMethod || m.isConstructor || (!m.isDeferred && m.isEffectivelyFinal) || m.allOverriddenSymbols.exists(o => supers.contains(o.owner)))
739+
val supervirts = virtualMethods(s.superClass)
740+
supervirts ++ (mymembers.toSet -- supervirts.toSet).toList.sortBy(methodSig _)
741+
/*
742+
val myvirts = s.info.decls.toList.filter(d => d.isMethod && !d.isConstructor && !(d.allOverriddenSymbols exists (m => !m.isDeferred)) && (d.isDeferred || !d.isEffectivelyFinal))
725743
(virtualMethods(s.superClass) ++ myvirts.sortBy(methodSig _)).toList
744+
*/
726745
}
727746
)
728747
}
@@ -882,8 +901,8 @@ abstract class GenLLVM extends SubComponent {
882901
}
883902

884903
def exportFunction(m: IMethod): Seq[ModuleComp] = {
885-
m.symbol.getAnnotation(ForeignExportAnnotSym) match {
886-
case Some(AnnotationInfo(_,List(Literal(Constant(foreignSymbol: String))),_)) => {
904+
m.symbol.getAnnotation(ForeignExportAnnotSym).get match {
905+
case AnnotationInfo(_,List(Literal(Constant(foreignSymbol: String))),_) => {
887906
val methType = m.symbol.info
888907
if (!m.symbol.isStatic) {
889908
error("Only object methods can be exported"); Seq.empty
@@ -1016,6 +1035,21 @@ abstract class GenLLVM extends SubComponent {
10161035
}
10171036
}
10181037

1038+
def genFieldFun(m: IField,i:Int) = {
1039+
val static = m.symbol.isStaticMember
1040+
val thisobj = new LocalVariable(".thisobj", rtObject.pointer)
1041+
val thisvar = new LocalVariable(".this", classType(c.symbol).pointer)
1042+
val fun = fieldPtrfun(m.symbol, static)
1043+
val src = if (static) externStaticP(c.symbol) else thisvar.asInstanceOf[LMValue[LMPointer]]
1044+
val prep = if (static) Seq() else Seq(new bitcast(thisvar, fun.args(0).lmvar))
1045+
val fieldptr = new LocalVariable("fieldptr", symType(m.symbol).pointer)
1046+
val idx = new CInt(LMInt.i32,if (static) i else i+1)
1047+
val body = Seq(LMBlock(Some(Label("start")), prep ++ Seq(
1048+
new getelementptr(fieldptr, src, Seq(new CInt(LMInt.i8,0),idx)),
1049+
new ret(fieldptr)
1050+
)))
1051+
fun.define(body)
1052+
}
10191053

10201054
def genNativeFun(m: IMethod) = {
10211055
val thisarg = ArgSpec(new LocalVariable(".this", symType(c.symbol)))
@@ -1077,7 +1111,7 @@ abstract class GenLLVM extends SubComponent {
10771111
Seq(header) ++ hblocks ++ Seq(footer)
10781112
}
10791113

1080-
m.code.blocks.filter(reachable).foreach { bb =>
1114+
m.code.blocks./*filter(reachable).*/foreach { bb =>
10811115
val stack: mutable.Stack[(LMValue[_<:ConcreteType],TypeKind)] = mutable.Stack()
10821116
def popn(n: Int) {
10831117
for (_ <- 0 until n) stack.pop
@@ -1086,7 +1120,7 @@ abstract class GenLLVM extends SubComponent {
10861120
val pass = Label("__PASS__")
10871121
val excpreds = bb.code.blocks.filter(pb => pb.exceptionSuccessors.contains(bb))
10881122
val dirpreds = bb.code.blocks.filter(_.directSuccessors contains bb)
1089-
val preds = (excpreds ++ dirpreds).filter(reachable)
1123+
val preds = (excpreds ++ dirpreds)/*.filter(reachable)*/
10901124
insns.append(new icomment("predecessors: "+preds.map(_.fullString).mkString(",")+" successors: "+bb.successors.map(_.fullString).mkString(" ")))
10911125
def loadobjvtbl(src: LMValue[SomeConcreteType])(implicit _insns: InstBuffer): LMValue[SomeConcreteType] = {
10921126
val asobj = nextvar(rtObject.pointer)
@@ -1244,15 +1278,15 @@ abstract class GenLLVM extends SubComponent {
12441278
recordType(lt)
12451279
if (tpe.isValueType || tpe == ConcatClass) {
12461280
val reg = new LocalVariable(blockName(bb)+".in."+n.toString,lt)
1247-
val dirsources = dirpreds.filter(reachable).map(pred => (blockLabel(pred,-1), new LocalVariable(blockName(pred)+".out."+n.toString,lt)))
1248-
val excsources = excpreds.filter(reachable).map(pred => (blockExSelLabel(pred,pred.method.exh.filter(_.covers(pred)).indexWhere(_.startBlock == bb)), new LocalVariable(blockName(pred)+".out."+n.toString,lt)))
1281+
val dirsources = dirpreds/*.filter(reachable)*/.map(pred => (blockLabel(pred,-1), new LocalVariable(blockName(pred)+".out."+n.toString,lt)))
1282+
val excsources = excpreds/*.filter(reachable)*/.map(pred => (blockExSelLabel(pred,pred.method.exh.filter(_.covers(pred)).indexWhere(_.startBlock == bb)), new LocalVariable(blockName(pred)+".out."+n.toString,lt)))
12491283
val sources = dirsources ++ excsources
12501284
insns.append(new phi(reg, sources))
12511285
stack.push((reg, tpe))
12521286
} else {
12531287
val asobj = nextvar(rtReference)
1254-
val dirsources = dirpreds.filter(reachable).map(pred => (blockLabel(pred,-1), new LocalVariable(blockName(pred)+".out."+n.toString,rtReference)))
1255-
val excsources = excpreds.filter(reachable).map(pred => (blockExSelLabel(pred,pred.method.exh.filter(_.covers(pred)).indexWhere(_.startBlock == bb)), new LocalVariable(blockName(pred)+".out."+n.toString,rtReference)))
1288+
val dirsources = dirpreds/*.filter(reachable)*/.map(pred => (blockLabel(pred,-1), new LocalVariable(blockName(pred)+".out."+n.toString,rtReference)))
1289+
val excsources = excpreds/*.filter(reachable)*/.map(pred => (blockExSelLabel(pred,pred.method.exh.filter(_.covers(pred)).indexWhere(_.startBlock == bb)), new LocalVariable(blockName(pred)+".out."+n.toString,rtReference)))
12561290
val sources = dirsources ++ excsources
12571291
insns.append(new phi(asobj, sources))
12581292
stack.push((cast(asobj, ObjectReference, tpe)(predcasts), tpe))
@@ -1320,27 +1354,36 @@ abstract class GenLLVM extends SubComponent {
13201354
}
13211355
case i@LOAD_FIELD(field, false) => {
13221356
val v = nextvar(symType(field))
1323-
val fieldptr = nextvar(v.tpe.pointer)
1357+
val fieldptr = nextvar(symType(field).pointer)
1358+
val (ivar,isym) = stack.pop
1359+
val instance = cast(ivar,isym,toTypeKind(field.owner.tpe))
1360+
val asobj = getrefptr(instance)
1361+
val instptr = nextvar(classType(field.owner).pointer)
1362+
insns.append(new bitcast(instptr, asobj))
1363+
insns.append(new invoke_void(rtAssertNotNull, Seq(asobj), pass, blockExSelLabel(bb,-2)))
1364+
insns.append(new call(fieldptr, externFieldFun(field, false), Seq(asobj)))
1365+
insns.append(new load(v, fieldptr))
1366+
stack.push((v,toTypeKind(field.tpe)))
1367+
/*
13241368
instFields(field.owner) match {
13251369
case Some(fi) =>
13261370
val fieldidx = fi.indexWhere(f => f.symbol == field)
13271371
assume(fieldidx >= 0)
1328-
val (ivar,isym) = stack.pop
1329-
val instance = cast(ivar,isym,toTypeKind(field.owner.tpe))
1330-
val asobj = getrefptr(instance)
1331-
val instptr = nextvar(classType(field.owner).pointer)
1332-
insns.append(new bitcast(instptr, asobj))
1333-
insns.append(new invoke_void(rtAssertNotNull, Seq(asobj), pass, blockExSelLabel(bb,-2)))
13341372
insns.append(new getelementptr(fieldptr, instptr.asInstanceOf[LMValue[LMPointer]], Seq(new CInt(LMInt.i8,0),new CInt(LMInt.i32,fieldidx+1))))
1335-
insns.append(new load(v, fieldptr))
1336-
stack.push((v,toTypeKind(field.tpe)))
13371373
case None =>
13381374
error("No field info for "+field.owner+" needed to lookup position of "+field)
13391375
m.dump
13401376
stack.push((new CUndef(v.tpe), toTypeKind(field.tpe)))
13411377
}
1378+
*/
13421379
}
13431380
case LOAD_FIELD(field, true) => {
1381+
val v = nextvar(symType(field))
1382+
val fieldptr = nextvar(v.tpe.pointer)
1383+
insns.append(new call(fieldptr, externFieldFun(field, true), Seq()))
1384+
insns.append(new load(v, fieldptr))
1385+
stack.push((v,toTypeKind(field.tpe)))
1386+
/*
13441387
val v = nextvar(symType(field))
13451388
val fieldptr = nextvar(v.tpe.pointer)
13461389
staticFields(field.owner) match {
@@ -1355,6 +1398,7 @@ abstract class GenLLVM extends SubComponent {
13551398
m.dump
13561399
stack.push((new CUndef(v.tpe), ObjectReference))
13571400
}
1401+
*/
13581402
}
13591403
case LOAD_MODULE(module) => {
13601404
insns.append(new call_void(moduleInitFun(module), Seq.empty))
@@ -1380,6 +1424,16 @@ abstract class GenLLVM extends SubComponent {
13801424
}
13811425
case STORE_FIELD(field, false) => {
13821426
val fieldptr = nextvar(symType(field).pointer)
1427+
val (value,valuesym) = stack.pop
1428+
val (ivar,isym) = stack.pop
1429+
val instance = cast(ivar,isym,toTypeKind(field.owner.tpe))
1430+
val asobj = getrefptr(instance)
1431+
val instptr = nextvar(classType(field.owner).pointer)
1432+
insns.append(new bitcast(instptr, asobj))
1433+
insns.append(new invoke_void(rtAssertNotNull, Seq(asobj), pass, blockExSelLabel(bb,-2)))
1434+
insns.append(new call(fieldptr, externFieldFun(field, false), Seq(asobj)))
1435+
insns.append(new store(cast(value, valuesym, toTypeKind(field.tpe)), fieldptr))
1436+
/*
13831437
instFields(field.owner) match {
13841438
case Some(fi) =>
13851439
val fieldidx = fi.indexWhere(f => f.symbol == field)
@@ -1396,9 +1450,14 @@ abstract class GenLLVM extends SubComponent {
13961450
case None =>
13971451
error("No field info for "+field.owner+" needed to lookup position of "+field)
13981452
}
1453+
*/
13991454
}
14001455
case STORE_FIELD(field, true) => {
14011456
val fieldptr = nextvar(symType(field).pointer)
1457+
val (value,valuesym) = stack.pop
1458+
insns.append(new call(fieldptr, externFieldFun(field, true), Seq()))
1459+
insns.append(new store(cast(value, valuesym, toTypeKind(field.tpe)), fieldptr))
1460+
/*
14021461
staticFields(field.owner) match {
14031462
case Some(fi) =>
14041463
val fieldidx = fi.indexWhere(f => f.symbol == field)
@@ -1409,6 +1468,7 @@ abstract class GenLLVM extends SubComponent {
14091468
case None =>
14101469
error("No field info for "+field.owner+" needed to lookup position of "+field)
14111470
}
1471+
*/
14121472
}
14131473
case CALL_PRIMITIVE(primitive) => {
14141474
primitive match {
@@ -2000,6 +2060,9 @@ abstract class GenLLVM extends SubComponent {
20002060
val methods = concreteMethods.filter(m => !CodegenAnnotations.exists(a => m.symbol.hasAnnotation(a)))
20012061
val llvmmethods = concreteMethods.filter(_.symbol.hasAnnotation(LlvmimplAnnotSym))
20022062
val methodFuns = methods.filter(_.code != NoCode).map(m => try { genFun(m) } catch { case e => println(e); m.dump; throw e } )
2063+
val staticFieldFuns = c.fields.filter(_.symbol.isStaticMember).zipWithIndex.map((genFieldFun _).tupled)
2064+
val nonstaticFieldFuns = c.fields.filterNot(_.symbol.isStaticMember).zipWithIndex.map((genFieldFun _).tupled)
2065+
val fieldFuns = staticFieldFuns ++ nonstaticFieldFuns
20032066
val llvmmethodFuns = llvmmethods.map(genNativeFun)
20042067
val foreignFuns = c.methods.filter(_.symbol.hasAnnotation(ForeignAnnotSym)).flatMap(genForeignFun)
20052068
val foreignVals = c.methods.filter(_.symbol.hasAnnotation(ForeignValueAnnotSym)).flatMap(genForeignVal)
@@ -2019,6 +2082,7 @@ abstract class GenLLVM extends SubComponent {
20192082
otherModules.keys.map(mod => moduleInitFun(mod).declare),
20202083
classInfo,
20212084
methodFuns,
2085+
fieldFuns,
20222086
llvmmethodFuns,
20232087
exportedFunctions,
20242088
foreignFuns,
@@ -2145,7 +2209,7 @@ abstract class GenLLVM extends SubComponent {
21452209
dir.fileNamed(llvmName(sym) + suffix)
21462210
}
21472211

2148-
/* used escapes: _ D L G S O M R A N */
2212+
/* used escapes: _ D L G S O M R A N F */
21492213

21502214
def encodeName(s: String) = {
21512215
s.replace("_","__")
@@ -2175,6 +2239,14 @@ abstract class GenLLVM extends SubComponent {
21752239
encodeName(sym.simpleName.toString.trim)
21762240
}
21772241

2242+
def fieldPtrfun(sym: Symbol, static: Boolean): LMFunction = {
2243+
val prefix = if (static) "static_" else ""
2244+
val funName = llvmName(sym.owner)+"_F"+llvmName(sym)
2245+
val restype = symType(sym).pointer
2246+
val args = if (static) Nil else List(ArgSpec(new LocalVariable("t", rtObject.pointer)))
2247+
new LMFunction(restype, funName, args, false, Externally_visible, Default, Ccc, Seq.empty, Seq.empty, None, None, None)
2248+
}
2249+
21782250
def blockLabel(bb: BasicBlock) = Label(blockName(bb))
21792251
def blockName(bb: BasicBlock) = "bb."+bb.label
21802252
def blockLabel(bb: BasicBlock, x: Int) = Label(blockName(bb,x))
@@ -2211,7 +2283,7 @@ abstract class GenLLVM extends SubComponent {
22112283

22122284
def stackUsage(bb: BasicBlock, memo: immutable.BitSet): (Seq[TypeKind],Seq[TypeKind]) = {
22132285
val (ict,ipt) = internalUsage(bb)
2214-
val predextras = bb.predecessors.filter(pb => reachable(pb) && !memo(pb.label)).headOption match {
2286+
val predextras = bb.predecessors.filter(pb => /*reachable(pb) &&*/ !memo(pb.label)).headOption match {
22152287
case Some(p) => stackUsage(p, memo+bb.label)._2.dropRight(ict.length)
22162288
case None => Seq.empty
22172289
}

src/llvm/library/scala/ffi/Storable.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object Storable extends ctypes.StorableCtypes
1414
}
1515

1616
trait Storable[T] {
17-
def size: Int
17+
def size: CSizeT
1818
def alignment: Int
1919
def peekElemOff(base: Ptr[T], n: Int): T = peek(base plus (n * size))
2020
def pokeElemOff(base: Ptr[T], n: Int, x: T): Unit = poke(base plus (n * size), x)

src/llvm/library/scala/ffi/alloc.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ object alloc {
55
@foreign("malloc") private def _malloc(n: CSizeT): CIntPtr = x
66
@foreign("free") private def _free(p: CIntPtr): Unit = x
77
def malloc[T:Storable]: Ptr[T] = { mallocBytes(Storable.get[Ptr[T]].size) }
8-
def mallocBytes[T](n: Long): Ptr[T] = Ptr.wrap(_malloc(n))
8+
def mallocBytes[T](n: CSizeT): Ptr[T] = Ptr.wrap(_malloc(n))
99
def free(p: Ptr[_]) = _free(Ptr.unwrap(p))
1010
def alloca[A:Storable,B](f: Ptr[A] => B): B = {
1111
val ptr: Ptr[A] = malloc
1212
if (ptr.isNull) throw new Exception()
1313
else try { f(ptr) } finally { free(ptr) }
1414
}
15-
def allocaBytes[A,B](n: Long)(f: Ptr[A] => B): B = {
15+
def allocaBytes[A,B](n: CSizeT)(f: Ptr[A] => B): B = {
1616
val ptr: Ptr[A] = mallocBytes(n)
1717
if (ptr.isNull) throw new Exception()
1818
else try { f(ptr) } finally { free(ptr) }

src/llvm/runtime/strings.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,3 +546,11 @@ method__Ojava_Dlang_DString_Mutf8bytes_Ajava_Dlang_DString_R_Nscala_DByte(
546546
return NULL;
547547
}
548548
}
549+
550+
struct java_lang_Object*
551+
method_java_Dlang_DString_MgetBytes_R_Nscala_DByte(
552+
struct java_lang_String *self, vtable_t selfVtable,
553+
vtable_t *vtableOut)
554+
{
555+
return method__Ojava_Dlang_DString_Mutf8bytes_Ajava_Dlang_DString_R_Nscala_DByte(NULL, NULL, self, selfVtable, vtableOut);
556+
}

0 commit comments

Comments
 (0)