Which lean C compiler for 32-bit OS development

W

Willem

Malcolm McLean wrote:
) On Nov 23, 7:28?am, Friedrich Dominicus <just-for-news-fr...@q-
) software-solutions.de> wrote:
)>
)> > He has added almost nothing of value to it: only an ugly GUI and a few
)> > non-standard proprietary language additions that are useless to anyone
)> > who wants to write portable code.
)>
)> You have ?not the slightest idea, but well you're not ?alone with that.
)>
) Not all code has to be portable. If you add something of value to a C
) compiler, really you have to add a non-standard feature. Otherwise
) your compiler isn't much different from anyone else's and there's no
) reason to choose it.

Well, you can compete in optimization, and you can also upgrade to a new
standard. C99, in this case. Oh, and a slick IDE is a selling point as
well.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

BartC

Brian said:
Sorry, but this is factually wrong.

Navia did not write the software. He bought the source code to lcc and
the rights to exploit it commercially.

He has added almost nothing of value to it: only an ugly GUI and a few
non-standard proprietary language additions that are useless to anyone
who wants to write portable code.

Well, the original LCC compiler is still available for download. Although
you will require an existing C compiler, and the know-how to be able to
build binaries for your platform. And, the time needed to write, acquire, or
modify various extras that lcc-win already provides (such as windows.h
perhaps).

It all sounds so straightforward! You wonder why someone doesn't spend an
hour or so doing this and provide binaries for people to use out-of-the-box.

In fact, Pelles C is also based on LCC! And this product is generally
well-regarded. It probably took rather more than an hour however.
 
J

jacob navia

Le 22/11/11 20:13, jacob navia a écrit :
Le 22/11/11 17:47, Brian a écrit :
rry, but this is factually wrong.

This is not true.

I have written for the compiler:

o The optimizer (Code of lcc-win is faster than plain lcc)
o New types supported like long double and long long.
o Ported the code generator to the new CPUs. XMM extensions of
the x86 CPU.
o Countless fixes and improvements during years of work.
o The assembler. Plain lcc generates ascii. Lcc-win writes object files.
o The linker. Plain lcc has no linker.
o The IDE.
o The debugger.
o The resource editor.
o The make and project handling utility.


lcc-win is C99. I wrote all necessary modifications to the compiler and
I wrote entirely the C99 C library.

But for these people, no lie will be enough.

Well, apparently "jo" and "Brian" kept silent. Until next time when
they will repeat their attacks, their lies, etc.

That is why I get so paranoiac... Years of this anonymous attacks can
transform someone into maybe someone else.

Easy to do for anonymous cowards like those.
 
N

Nick Keighley

Sorry, but this is factually wrong.

Navia did not write the software. He bought the source code to lcc and
the rights to exploit it commercially.

He has added almost nothing of value to it:

I'm pretty sure this is untrue. He's added a wide variety of
extensions and support tools. I'm pretty sure the debugger and
assembler or entirely his. A debugger is *very* non-trivial. The C99
featurs are his too.
only an ugly GUI and a few
non-standard proprietary language additions that are useless to anyone
who wants to write portable code.

Not everyone does.
 
N

Nick Keighley

I was happy with LCC-Win until I started to use FLTK that requires
C++. I found the IDE to be clean without a whole bunch of (dockable)
windows reducing screen realestate. I wish MinGw compiled as fast as
LCC-Win.

As for "proprietary language additions". You are not compelled to use
these non portable additions, they are purly optional.

after all gcc is crawling with bizzare extensions
 
M

Malcolm McLean

Well, you can compete in optimization, and you can also upgrade to a new
standard.  C99, in this case.  Oh, and a slick IDE is a selling pointas
well.
Optimisation is a bit one-dimensional. If you have the most optimal
compiler on the market, you have a unique selling point. But that's
hard to achieve, and you'll likely lose the selling point as the
competition catches up. A better strategy is to segment the
marketplace, e.g. target people who want garbage collection.

There doesn't seem to be much demand for C99. It's a failed standard.
 
J

James Harris

You are not looking for C at all.  You are looking for defining your own
ABI and using it on a bunch of systems.

Your comments are 'robust'. I will return the compliment. :)

You are being naive, Peter. If C is the best tool for the job it makes
sense to use it. Period. There is no point ignoring C for this task
because it is not perfect. Nothing is. C is by far the best HLL I know
of for what I want to do so it makes sense to use it.
Basically, you're Doing It Wrong.  If you want to use C, *USE C*.  Work
with the language the way it is designed, rather than trying to outsmart
it.

For just about all the C programming I have ever done I have had to
interface with no other programming languages. In this project that is
not the case. The C code will have to work with code written in other
languages, if only assembler.

As things stand I will have to adjust the asm to dovetail with one of
the calling conventions of the C compiler I choose. I would *prefer*
the option to customise the compiler's output to conventions that I
select - but I recognise that may not be possible.

Taking a step back, consider a C anomaly. Look at how low-level C is
and why it is favoured as a 'portable assembler' (not a phrase I am
recommending) by compiler writers and others. In C there is usually a
clear, direct and simple correspondence between C operations and a
CPU's opcodes, and a similar correspondence between C data types and
those supported by the CPU.

However, this simple one-to-one mapping of C features to CPU features
does not apply to subroutine calls and function prologues and
epilogues. In this case (like no other in the language?) C generates a
slew of instructions for one source language construct. I understand
why and agree with the choice. C was meant to interface with C.
However, it is a distinct difference in the level of the language. I
was commenting on the lack of control over this part of the object
code.
And that means that you don't waste valuable time and effort trying to
figure out ways to avoid recompiling on new targets, because *that is
silly*.  The entire point of C is that you can *recompile* on new targets,
not that you can make magical binaries which are portable across unrelated
targets.

You misunderstand. I was not talking about avoiding recompilation. I
was talking, in part, about interfacing C with non-C.
Then, all the "problems" go away.  You don't care what compiler any given
target has as long as it supports the standard.  You don't care what CPU
is in use, or anything like that.  Poof!  Problem solved by using thetool
for the purpose it was designed for.

This is true for most C programming but if you are saying this is
universally true I don't agree. In my case the OS has distinct address
space, tasking and resource models. This is the other part of what I
was talking about: interfacing C with the desired OS models. So I *do*
care what the compiler generates. It matters to the goals of the
project.

James
 
I

Ian Collins

For just about all the C programming I have ever done I have had to
interface with no other programming languages. In this project that is
not the case. The C code will have to work with code written in other
languages, if only assembler.

As things stand I will have to adjust the asm to dovetail with one of
the calling conventions of the C compiler I choose. I would *prefer*
the option to customise the compiler's output to conventions that I
select - but I recognise that may not be possible.

You haven't really said what you are trying to do. Are you targeting a
hosted platform? If so the function call ABI will already be well defined.
Taking a step back, consider a C anomaly. Look at how low-level C is
and why it is favoured as a 'portable assembler' (not a phrase I am
recommending) by compiler writers and others. In C there is usually a
clear, direct and simple correspondence between C operations and a
CPU's opcodes, and a similar correspondence between C data types and
those supported by the CPU.

Once upon a time long ago, maybe. This certainly isn't the case today.
However, this simple one-to-one mapping of C features to CPU features
does not apply to subroutine calls and function prologues and
epilogues. In this case (like no other in the language?) C generates a
slew of instructions for one source language construct. I understand
why and agree with the choice. C was meant to interface with C.
However, it is a distinct difference in the level of the language. I
was commenting on the lack of control over this part of the object
code.

The "lack of control" is because the function call ABI is defined for
the platform/CPU outside of the C standard. To invent some arbitrary
ABI that does not conform with the host is pointless.
You misunderstand. I was not talking about avoiding recompilation. I
was talking, in part, about interfacing C with non-C.

Which is often define in the "non C" language specification.
This is true for most C programming but if you are saying this is
universally true I don't agree. In my case the OS has distinct address
space, tasking and resource models. This is the other part of what I
was talking about: interfacing C with the desired OS models. So I *do*
care what the compiler generates. It matters to the goals of the
project.

So you you are using an OS without a well defined ABI?
 
S

Seebs

You are being naive, Peter. If C is the best tool for the job it makes
sense to use it. Period. There is no point ignoring C for this task
because it is not perfect. Nothing is. C is by far the best HLL I know
of for what I want to do so it makes sense to use it.

If you want to use it, then use it!

Your theory here is roughly equivalent to pounding screws in with a hammer
becasue the hammer is the best tool you know of.
As things stand I will have to adjust the asm to dovetail with one of
the calling conventions of the C compiler I choose. I would *prefer*
the option to customise the compiler's output to conventions that I
select - but I recognise that may not be possible.

Probably the best solution would be to use inline assembly, which most
compilers can integrate nicely.

It seems to me like the impression I got was not correct. My understanding
was that you wanted to compile C, once, to a binary form and then use those
binaries unmodified on a variety of systems. This is the Wrong Way To Do It.

If you need to interact with assembly, the usual way to do it is to use
either compiler-specific inline assembly things, or system-specific hunks of
glue.

It'd probably be easier to give better advice with a clearer and higher-level
idea of what you're trying to do.

-s
 
J

James Harris

On 12/11/11 08:29 AM, James Harris wrote:
....

You haven't really said what you are trying to do.  Are you targeting a
hosted platform?  If so the function call ABI will already be well defined.

I did say (in the title/subject) that this is for development of an OS
- an operating system. As such, no, this is not for a hosted platform.
The 'platform' itself is being defined, as is the ABI.
Once upon a time long ago, maybe.  This certainly isn't the case today.

I don't understand but am interested in the idea. What has changed to
make this no longer the case?
The "lack of control" is because the function call ABI is defined for
the platform/CPU outside of the C standard.  To invent some arbitrary
ABI that does not conform with the host is pointless.

As the OS is new there is no host software at all. The OS's use of the
CPU is fairly generic and could apply to various processors. So all of
the structure and interface is up for definition.

....
So you you are using an OS without a well defined ABI?

Well, the interface to the OS will be well defined but the design is
intended to be based on first principles and, as far as possible, to
avoid influence from existing systems.

Sorry to be vague about the OS internals. They are well off-topic for
c.l.c.

James
 
I

Ian Collins

I did say (in the title/subject) that this is for development of an OS
- an operating system. As such, no, this is not for a hosted platform.
The 'platform' itself is being defined, as is the ABI.

Well that clarifies things. You would still be well advised to follow
existing practice for your ABI. If nothing else, that will simplify
writing a gcc port for your platform. For some processors (AMD64,
Sparc) calling conventions are well defined.
I don't understand but am interested in the idea. What has changed to
make this no longer the case?

Optimisation technology.
 
J

James Harris

If you want to use it, then use it!

Your theory here is roughly equivalent to pounding screws in with a hammer
becasue the hammer is the best tool you know of.

Analogies paint mental images but are not necessarily apt. In fact C
is a better fit than your analogy suggests - but it's not perfect.
Why? In this case perhaps it's like a screwdriver that doesn't just
drive in screws - i.e. it doesn't just do at the assembler level what
it's been told in the HLL. It does a relatively complex subroutine
linkage too.

When you think about it there's quite a lot of choices that a C
compiler takes on itself when calling subroutines: how to pass
parameters, which should be caller- and callee-save registers, how to
locate the target and how to return results. Pretty much none of these
fit my current plan!
Probably the best solution would be to use inline assembly, which most
compilers can integrate nicely.

I understand the suggestion and can see its sense but it doesn't work
for me for two reasons: 1) inline asm is awful to work with compared
with my preferred assembler, Nasm and 2) such a course wouldn't remove
the subroutine linkage that is the cause of the problem. Interfacing
with another language is just one part of the requirement. The other
is implementing a specific form of interface between the modules that
make up the OS. No language I know of other than assembler allows
these things to be defined.
It seems to me like the impression I got was not correct.  My understanding
was that you wanted to compile C, once, to a binary form and then use those
binaries unmodified on a variety of systems.  This is the Wrong Way To Do It.

Right. That is not the intention.
If you need to interact with assembly, the usual way to do it is to use
either compiler-specific inline assembly things, or system-specific hunksof
glue.

Agreed. I have plans to develop the system itself as pure as possible
and later provide glue code to interface with more traditional
systems.
It'd probably be easier to give better advice with a clearer and higher-level
idea of what you're trying to do.

Thanks for taking an interest but my plans are well off topic for this
newsgroup and are still being formed so I won't bore people here with
them.

I have an answer to the original question: despite some negatives such
as its size gcc appears to be the closest fit to what I was looking
for. However, I have found that trying to work with it tends to
constrain the design. I keep finding I am making the design fit the
compiler. So for the time being I am sticking with assembler. Once the
design is stable I will look at interfacing to HLLs and compilers.

James
 
S

Seebs

I did say (in the title/subject) that this is for development of an OS
- an operating system. As such, no, this is not for a hosted platform.
The 'platform' itself is being defined, as is the ABI.

I would point out that ABIs are often defined by the architecture in some
way. There is a "MIPS ABI" (well, there's several) which exists independent
of your choice of operating system.
I don't understand but am interested in the idea. What has changed to
make this no longer the case?

Well, strictly speaking, it never was. Consider:

long a, b, c;
a = get_a_number();
b = get_a_number();
c = a * b;

I'm pretty sure this has been implemented in software on at least some C
implementations since the 70s, because there have been 32-bit longs on 16-bit
systems.

Similarly, 64-bit values on 32-bit systems, floating point math on machines
with no FPU... The list goes on, and on, and on.

C hasn't really been much for 1:1 correspondences in a very long time. I
think the most obvious cutoff, if you wanted one, would be struct assignment.
As the OS is new there is no host software at all. The OS's use of the
CPU is fairly generic and could apply to various processors. So all of
the structure and interface is up for definition.

If you don't use a standard ABI for each CPU, you will have a much harder
time.
Well, the interface to the OS will be well defined but the design is
intended to be based on first principles and, as far as possible, to
avoid influence from existing systems.

I think C is the wrong tool for this, then, as a great deal of the benefit of
C is a mature ecosystem for using standard ABIs.

-s
 
S

Seebs

Analogies paint mental images but are not necessarily apt. In fact C
is a better fit than your analogy suggests - but it's not perfect.
Why? In this case perhaps it's like a screwdriver that doesn't just
drive in screws - i.e. it doesn't just do at the assembler level what
it's been told in the HLL. It does a relatively complex subroutine
linkage too.

Well, yes. That's necessary for it to do its job.
When you think about it there's quite a lot of choices that a C
compiler takes on itself when calling subroutines: how to pass
parameters, which should be caller- and callee-save registers, how to
locate the target and how to return results. Pretty much none of these
fit my current plan!

Then C is probably the wrong tool, because the entire *point* of C is to
Make That Go Away. This is supposed to be a language you can use in
complete ignorance of whether your target system even *has* registers,
let alone how many, what sizes, or what rules they follow. If you need
to think about things like that, you need a different category of tool.
I understand the suggestion and can see its sense but it doesn't work
for me for two reasons: 1) inline asm is awful to work with compared
with my preferred assembler, Nasm and 2) such a course wouldn't remove
the subroutine linkage that is the cause of the problem. Interfacing
with another language is just one part of the requirement. The other
is implementing a specific form of interface between the modules that
make up the OS. No language I know of other than assembler allows
these things to be defined.

Ayup. That's because it's not even coherent to speak of defining them
outside of an absolute commitment to a specific CPU.

.... BTW, I should point out, even though I don't currently think this will
work out as you've described it, it's been a nice change disagreeing with
someone who appears to be basically lucid. I'm sorry if I come across as
harsh; I don't think what you're doing is stupid or crazy, I just think it's
probably not going to turn out to be a good fit for C unless you feel like
developing your own compiler for it.

-s
 
J

James Harris

Well that clarifies things.
Great.

You would still be well advised to follow
existing practice for your ABI.  If nothing else, that will simplify
writing a gcc port for your platform.

I understand the point. However, from what I have done so far I can
see it would be easy to miss useful innovations by being influenced by
existing systems. The whole point of writing a new OS is to do things
in a new way. So my intention is as far as possible to make a clean
design and then to provide interfacing as needed.

If I can wax lyrical for a moment: How often does a programmer get to
write something that is totally independent of existing systems?
Almost never. We work with specific operating systems such as Unix,
Windows, DOS etc. We work with specific libraries such as sockets and
various GUIs and we work with specific file formats such as Elf, jpeg
etc. And we work with specific concepts such as files and data
streams. *All* of these are up for grabs when writing an OS.

If anyone is interested in looking at this there is some info at

http://aodfaq.wikispaces.com/

put together by a bunch of people doing similar.
For some processors (AMD64,
Sparc) calling conventions are well defined.



Optimisation technology.

I don't see this. I was talking about how C operations are those you
will find on a CPU's ALU: arithmetic, shifts, bitwise operations; and
how C's data types map to typical CPU data types: signed and unsigned
integers and bitfields of different widths, floats of differing types.
Surely these are not dependent on optimisation.

James
 
I

Ian Collins

I understand the point. However, from what I have done so far I can
see it would be easy to miss useful innovations by being influenced by
existing systems. The whole point of writing a new OS is to do things
in a new way. So my intention is as far as possible to make a clean
design and then to provide interfacing as needed.

Consider this: why would the designers of an OS ABI choose an
inefficient calling convention?
If I can wax lyrical for a moment: How often does a programmer get to
write something that is totally independent of existing systems?
Almost never. We work with specific operating systems such as Unix,
Windows, DOS etc. We work with specific libraries such as sockets and
various GUIs and we work with specific file formats such as Elf, jpeg
etc. And we work with specific concepts such as files and data
streams. *All* of these are up for grabs when writing an OS.

They are also frequently up for grabs in embedded systems, where most C
programmers operate these days.

I don't see this. I was talking about how C operations are those you
will find on a CPU's ALU: arithmetic, shifts, bitwise operations; and
how C's data types map to typical CPU data types: signed and unsigned
integers and bitfields of different widths, floats of differing types.
Surely these are not dependent on optimisation.

You could say the same for any programming language. C does allow you
to specify exact with types, but they are provided to enable C to
interface with low level entities. Most C programs won't use them.

How an instance of a type is manipulated is very much dependent on
optimisation. A declared variable may not even exist in optimised code.
The machine instructions emitted by an optimising compiler often bear
little resemblance to the code written by the programmer. Functions get
inlined, instructions get reordered and so on.
 
J

jacob navia

Le 11/12/11 00:10, James Harris a écrit :
I have an answer to the original question: despite some negatives such
as its size gcc appears to be the closest fit to what I was looking
for. However, I have found that trying to work with it tends to
constrain the design. I keep finding I am making the design fit the
compiler. So for the time being I am sticking with assembler. Once the
design is stable I will look at interfacing to HLLs and compilers.

Gcc is too big for what you want. You need a compiler that you can
possibly understand or have someone that can help you out with a
question, etc.

There are (maybe) 10-20 people in the world that have a very detailed
knowledge of gcc in all its complexity.


Once I needed to interface my code with gcc, and needed to know
how the exception handling is implemented in gcc, specially in
C++/Linux.

It took me 5-6 MONTHS.

o Wrong documentation or inexsiting documentation. I used the
specs of the ABI only to find out that gcc doesn't implement
all of it and "enhances" most of the implementation. When
asking questions I always got the same answer:

You have the source!

Huge files implement that part, without a single comment in them
besides the GNU copyright stuff. Yes; just understand something
in there.

o I asked the guy that knew the stuff (working at RedHat). He told
me I would have to buy a RedHat maintenance contract for support
for a year: US$ 25,000.

o Bad design. For instance, you write in the assembler
.byte 0x38
and expect (naively) that the corresponding value will
appear in the object file. No, it doesn't.

When I filed a bug report, they told me that for certain
sections, the assembler "optimizes" the writing of the
values and ignores some. Great.

o There is NO WAY you will be able to understand gcc enough
to make any modifications to it unless you spend several
years working. You understimate badly the problem.

I tried to fix a bug, some time ago. Floating point stdcall
functions under windows would crash... bad code was generated.

I worked for 2 weeks before giving up. Try understanding their
"RTL" then the different structures and hacks, etc. You will
get nowhere, and you will never be able to modify anything.

You can verify this. Just TRY to modify a minimal thing.



Of course I am biased. But you will be able to verify all I am saying.
Just try to make a trivial modification within gcc, say for instance
you want to use in your os always a stdcall calling convention and
instead of returning with

ret

you always

ret $n

where n is the number of words in the stack pushed by the caller.

Have fun!

jacob
 
S

Seebs

I understand the point. However, from what I have done so far I can
see it would be easy to miss useful innovations by being influenced by
existing systems. The whole point of writing a new OS is to do things
in a new way. So my intention is as far as possible to make a clean
design and then to provide interfacing as needed.

Hmm. Well, it's an interesting experiment, anyway. I'm not sure I'd expect
it to yield significant advantages.
If I can wax lyrical for a moment: How often does a programmer get to
write something that is totally independent of existing systems?
Almost never.

I have rarely *wanted* to. Interactions with stuff is what makes things
interesting.
I don't see this. I was talking about how C operations are those you
will find on a CPU's ALU: arithmetic, shifts, bitwise operations; and
how C's data types map to typical CPU data types: signed and unsigned
integers and bitfields of different widths, floats of differing types.
Surely these are not dependent on optimisation.

For an obvious example that someone recently brought up: Many ARM processors
lack a divider in hardware.

So there's often, for even the most primitive operations, substantial code
generation going on behind the scenes.

-s
 
J

James Kuyper

On 12/10/2011 02:29 PM, James Harris wrote:
....
... In C there is usually a
clear, direct and simple correspondence between C operations and a
CPU's opcodes, and a similar correspondence between C data types and
those supported by the CPU.

Not all machines had opcodes that match every C operations, and not all
C operations have corresponding single opcodes on every machine. Many
operations have long been emulated on some machines rather than being
directly supported; such as 32-bit integers on 8-bit machines, or 8-bit
types on 32-bit machines, or floating point operations on machines with
no FPU.

Also, optimization has always rendered the relationship less than
perfectly "clear, direct, and simple". Compare the assembly code
generated by the highest optimization level for a typical compiler with
your original C code; if the relationship is at all "clear, direct, and
simple", it's probably a compiler whose optimization capabilities are
substantially inferior to the current state of the art.
 
8

88888 Dihedral

On 12/10/2011 02:29 PM, James Harris wrote:
...

Not all machines had opcodes that match every C operations, and not all
C operations have corresponding single opcodes on every machine. Many
operations have long been emulated on some machines rather than being
directly supported; such as 32-bit integers on 8-bit machines, or 8-bit
types on 32-bit machines, or floating point operations on machines with
no FPU.

Also, optimization has always rendered the relationship less than
perfectly "clear, direct, and simple". Compare the assembly code
generated by the highest optimization level for a typical compiler with
your original C code; if the relationship is at all "clear, direct, and
simple", it's probably a compiler whose optimization capabilities are
substantially inferior to the current state of the art.

Yes, there was an European software company bought by the British arm company.
I thought that was a good move to kill obsolete 8051-8052 by the 32 bit arm.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,184
Latest member
ZNOChrista

Latest Threads

Top