Hacking uSwift, a minimal stdlib... where is getOptionalDecl() defined?

OK, I'm going mad here I think.

I'm putting together a minimal stdlib, partly for fun, partly for profit, who knows?

Anyway, my latest stumbling block is why my code for public enum Optional<Wrapped> isn't being recognised. Looking through compiler source, the error generated (error: broken standard library: cannot find Optional type) seems to be coming from calling getOptionalDecl() and getting back a nil.

The thing is, I cannot find where this function exists! There are lots of calls to it (20 or so) throughout the swift source code but I can't find the function definition so I can't figure out why it's breaking.

Can anyone help? I feel like I'm going mad or missing something important!

Carl

1 Like

@carlos4242 Have you taken a look at this:

https://github.com/apple/swift/blob/master/test/SILGen/minimum_foreach.swift

This shows the minimum amount of code to get swift to emit a foreach. There it includes an implementation of optional/etc enough to get things to compile so you can use foreach (which relies on optional).

1 Like

That's a lovely little example and a great use of tests as documentation. Thanks :slight_smile:

Looking at the RUN: line on the test gave me the clue that has got me to the next step. The module name! My build script was building my uSwift.swift file with some random module name. I changed the module-name to Swift and it seems to be able to find it now. I'm progressing through next steps, when I've got a simple working version I'll put it up somewhere for people to pore over.

It still does leave me with my original puzzle though, where in the source code is the implementation of getOptionalDecl()?

I think that getOptionalDecl() looks up Swift.Optional. It expects Optional to be in a module named Swift. If you had the wrong name, Swift will not find it if you give it the wrong module name. Just a guess.

Answer to the original question:

2 Likes

Yeah, the KnownStdlibTypes.def file, along with its close cousins KnownDecls.def and KnownProtocols.def, should give you some sense of what the compiler expects to exist at minimum in the standard library. If there are incidental requirements on standard library definitions not in one of those files, then I think it'd be good to refactor the compiler to use one of the .def files, so that anyone else interested in developing a micro-stdlib might have a canonical list of requirements they need to fill in.

2 Likes

@jrose .. great! Thanks for the help. That explains it. :slight_smile:

@Joe_Groff, thanks for that, good hint. You seem to know quite a lot about Swift. ;)

Cheers guys,
Carl

A quick status update. I've got a super basic uSwift file. It's too rough and buggy to share yet, once I can build from it I'll put it up. There's a surprisingly large amount of boilerplate around ints. Basically all it contains are some core operator definitions/protocols, Optional, Ints, Bool and some pointers, not even binary integer arithmetic (yet) and it already runs well over 1000 lines. lol. The current bugbears: if I use my compiled Swift module to compile a sample file, I get error: no such module 'SwiftOnoneSupport' unless i turn on optimisation (but I'm fine with optimisation and can emit a library module based on uSwift); and some weird error inside the LLVM backend when actually emitting code, which is probably AVR related so i'll look into it as that's my area.

3 Likes

SwiftOnoneSupport is a special case library that's injected for non-optimized builds. You may want to disable it when building in your no-runtime mode, though you probably need to enable optimization anyway currently in order to sufficiently eliminate runtime calls for other reasons. You could try using the gyb tool, which the standard library uses to reduce boilerplate by generating code from templates with embedded python code, to reduce the amount of copied code you need for things like integer types.

Super interesting to follow your explorations! Thanks for sharing!

@Joe_Groff, yes, I thought of using the templating tool, though I hadn't worked out how, good call... with swiftonone I'm going to be doing optimised builds most of the time so I won't need it but in my case a stub version will be fine. :slight_smile:, just out of curiosity, why is it in a different module to the standard library?

We separate SwiftOnoneSupport out because it contains code that is always inlined and optimized out of release builds, but not in unoptimized builds, as a balance to reduce code size and compilation time for unoptimized builds without burdening shipping binaries with having to carry that extra code around. For your project, you can probably do completely without it.

2 Likes

Makes sense.

OK, next issue. :slight_smile:

(***left here for completeness but i started a new question for this... "Assertion failed: (isa<X>(Val) && “cast<Ty>() argument of incompatible type!”) from clang when trying to compile with an unusual target" ***)

When i'm compiling swift code to LLVM IR using my built version of swift, I'm getting a trap within the constructor for swift::irgen::IRGenModule. Specifically, the last line, IsSwiftErrorInRegister = clang::CodeGen::swiftcall::isSwiftErrorLoweredInRegister( ClangCodeGen->CGM());

Clang shows this method is simply...

// Is swifterror lowered to a register by the target ABI.
bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) {
  return getSwiftABIInfo(CGM).isSwiftErrorInRegister();
}

getSwiftABIInfo traps with...

Assertion failed: (isa<X>(Val) && "cast<Ty>() argument of incompatible type!"), function cast, file /Users/carlpeto/avr/swift/llvm/include/llvm/Support/Casting.h, line 248.

The code in question looks simple...

static const SwiftABIInfo &getSwiftABIInfo(CodeGenModule &CGM) {
  return cast<SwiftABIInfo>(CGM.getTargetCodeGenInfo().getABIInfo());
}

So my best guess is that CGM.getTargetCodeGenInfo().getABIInfo() returns ABI info that's not Swift ABI info, whatever that means.

Does anyone have any ideas why that might be?

Tracked that problem down. See the other question for answers.

Is anyone interested in the source code for the basic stdlib I can try to upload it on my github account for people to look at but it's very unfinished and hacked. I'm not honestly sure it would be any use to anyone except just for curiousity. :slight_smile:

1 Like

If you run into other Swift calling convention related issues, @John_McCall or @Arnold may be able to help. I believe it's possible to say that a target platform has no swiftcc support at all, which should cause us to use reasonable fallback mechanisms in terms of the default cc.

1 Like

I think we dropped that; you don’t have to do anything special in the backend for it if you’re happy enough with your standard ABI, but we do want you to accept swiftcc on your target.

Oh yes! That would be good! I've noticed functions being marked with swiftcc in the IR and I'm not sure why. Any advice on how to disable this for my target would be fantastic!