Skip to content

Commit 7c94f26

Browse files
committed
make backends set feature versions instead of the core
1 parent 2ebc0df commit 7c94f26

File tree

7 files changed

+137
-22
lines changed

7 files changed

+137
-22
lines changed

examples/extern.cal

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
requires Linux86
2+
3+
include "cores/select.cal"
4+
include "std/nullterm.cal"
5+
6+
extern raw puts
7+
8+
func cputs begin
9+
let addr str
10+
Array.elements + @ str !
11+
str @ __linux86_pop_rdi puts
12+
end
13+
14+
"Hello, world!\n\0" cputs

source/app.d

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Flags:
2929
-dp - Prints parser output
3030
-es - Export all Callisto symbols (and add util functions for interacting
3131
with the Callisto stack)
32+
-d - Enables debug symbols (if available)
33+
-l LIB - Links LIB with the linker (if available)
3234
3335
Backends:
3436
rm86 - Real mode x86 and MS-DOS
@@ -57,6 +59,7 @@ int main(string[] args) {
5759
bool doDebug;
5860
bool debugParser;
5961
bool exportSymbols;
62+
string[] link;
6063

6164
for (size_t i = 1; i < args.length; ++ i) {
6265
if (args[i][0] == '-') {
@@ -165,6 +168,16 @@ int main(string[] args) {
165168
exportSymbols = true;
166169
break;
167170
}
171+
case "-l": {
172+
++ i;
173+
if (i >= args.length) {
174+
stderr.writeln("-l expects LIB argument");
175+
return 1;
176+
}
177+
178+
link ~= args[i];
179+
break;
180+
}
168181
default: {
169182
stderr.writefln("Unknown flag '%s'", args[i]);
170183
return 1;
@@ -203,6 +216,7 @@ int main(string[] args) {
203216
compiler.backend.orgSet = orgSet;
204217
compiler.backend.useDebug = doDebug;
205218
compiler.backend.exportSymbols = exportSymbols;
219+
compiler.backend.link = link;
206220

207221
versions ~= compiler.backend.GetVersions();
208222

source/backends/linux86.d

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import callisto.compiler;
1212
import callisto.language;
1313

1414
private struct Word {
15+
bool raw;
1516
bool inline;
1617
Node[] inlineNodes;
1718
}
@@ -132,20 +133,38 @@ class BackendLinux86 : CompilerBackend {
132133
}
133134

134135
override string[] GetVersions() => [
135-
"Linux86", "Linux", "LittleEndian", "16Bit", "32Bit", "64Bit"
136+
// platform
137+
"Linux86", "Linux", "LittleEndian", "16Bit", "32Bit", "64Bit",
138+
// features
139+
"IO", "Exit", "Time", "File"
136140
];
137141

138-
override string[] FinalCommands() => [
139-
format("mv %s %s.asm", compiler.outFile, compiler.outFile),
140-
useDebug?
141-
format(
142-
"nasm -f elf64 %s.asm -o %s.o -F dwarf -g", compiler.outFile,
143-
compiler.outFile
144-
) :
145-
format("nasm -f elf64 %s.asm -o %s.o", compiler.outFile, compiler.outFile),
146-
format("ld %s.o -o %s", compiler.outFile, compiler.outFile),
147-
format("rm %s.asm %s.o", compiler.outFile, compiler.outFile)
148-
];
142+
override string[] FinalCommands() {
143+
string[] ret = [
144+
format("mv %s %s.asm", compiler.outFile, compiler.outFile),
145+
useDebug?
146+
format(
147+
"nasm -f elf64 %s.asm -o %s.o -F dwarf -g", compiler.outFile,
148+
compiler.outFile
149+
) :
150+
format("nasm -f elf64 %s.asm -o %s.o", compiler.outFile, compiler.outFile)
151+
];
152+
153+
string linkCommand = format("ld %s.o -o %s", compiler.outFile, compiler.outFile);
154+
155+
foreach (ref lib ; link) {
156+
linkCommand ~= format(" -l%s", lib);
157+
}
158+
159+
if (!link.empty()) {
160+
// idk if this is correct on all linux systems but whatever
161+
linkCommand ~= " -dynamic-linker /lib64/ld-linux-x86-64.so.2";
162+
}
163+
164+
ret ~= linkCommand;
165+
166+
return ret ~ format("rm %s.asm %s.o", compiler.outFile, compiler.outFile);
167+
}
149168

150169
override void BeginMain() {
151170
output ~= "__calmain:\n";
@@ -258,7 +277,12 @@ class BackendLinux86 : CompilerBackend {
258277
}
259278
}
260279
else {
261-
output ~= format("call __func__%s\n", node.name.Sanitise());
280+
if (word.raw) {
281+
output ~= format("call %s\n", node.name);
282+
}
283+
else {
284+
output ~= format("call __func__%s\n", node.name.Sanitise());
285+
}
262286
}
263287
}
264288
else if (VariableExists(node.name)) {
@@ -307,13 +331,13 @@ class BackendLinux86 : CompilerBackend {
307331
thisFunc = node.name;
308332

309333
if (node.inline) {
310-
words[node.name] = Word(true, node.nodes);
334+
words[node.name] = Word(false, true, node.nodes);
311335
}
312336
else {
313337
assert(!inScope);
314338
inScope = true;
315339

316-
words[node.name] = Word(false, []);
340+
words[node.name] = Word(false, false, []);
317341

318342
if (exportSymbols) {
319343
output ~= format("global __func__%s\n", node.name.Sanitise());
@@ -707,4 +731,14 @@ class BackendLinux86 : CompilerBackend {
707731
types[node.to] = types[node.from];
708732
NewConst(format("%s.sizeof", node.to), cast(long) types[node.to].size);
709733
}
734+
735+
override void CompileExtern(ExternNode node) {
736+
Word word;
737+
word.raw = node.raw;
738+
words[node.func] = word;
739+
740+
if (word.raw) {
741+
output ~= format("extern %s\n", node.func);
742+
}
743+
}
710744
}

source/backends/rm86.d

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import callisto.compiler;
1212
import callisto.language;
1313

1414
private struct Word {
15+
bool raw;
1516
bool inline;
1617
Node[] inlineNodes;
1718
}
@@ -127,7 +128,10 @@ class BackendRM86 : CompilerBackend {
127128
}
128129

129130
override string[] GetVersions() => [
130-
"RM86", "LittleEndian", "16Bit"
131+
// platform
132+
"RM86", "LittleEndian", "16Bit",
133+
// features
134+
"IO"
131135
];
132136

133137
override string[] FinalCommands() => [
@@ -191,7 +195,12 @@ class BackendRM86 : CompilerBackend {
191195
}
192196
}
193197
else {
194-
output ~= format("call __func__%s\n", node.name.Sanitise());
198+
if (word.raw) {
199+
output ~= format("call %s\n", node.name);
200+
}
201+
else {
202+
output ~= format("call __func__%s\n", node.name.Sanitise());
203+
}
195204
}
196205
}
197206
else if (VariableExists(node.name)) {
@@ -232,13 +241,13 @@ class BackendRM86 : CompilerBackend {
232241
thisFunc = node.name;
233242

234243
if (node.inline) {
235-
words[node.name] = Word(true, node.nodes);
244+
words[node.name] = Word(false, true, node.nodes);
236245
}
237246
else {
238247
assert(!inScope);
239248
inScope = true;
240249

241-
words[node.name] = Word(false, []);
250+
words[node.name] = Word(false, false, []);
242251

243252
output ~= format("__func__%s:\n", node.name.Sanitise());
244253

@@ -635,4 +644,10 @@ class BackendRM86 : CompilerBackend {
635644
types[node.to] = types[node.from];
636645
NewConst(format("%s.sizeof", node.to), cast(long) types[node.to].size);
637646
}
647+
648+
override void CompileExtern(ExternNode node) {
649+
Word word;
650+
word.raw = node.raw;
651+
words[node.func] = word;
652+
}
638653
}

source/compiler.d

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class CompilerBackend {
1717
Compiler compiler;
1818
bool useDebug;
1919
bool exportSymbols;
20+
string[] link;
2021

2122
abstract string[] GetVersions();
2223
abstract string[] FinalCommands();
@@ -42,6 +43,7 @@ class CompilerBackend {
4243
abstract void CompileContinue(WordNode node);
4344
abstract void CompileUnion(UnionNode node);
4445
abstract void CompileAlias(AliasNode node);
46+
abstract void CompileExtern(ExternNode node);
4547

4648
final void Error(Char, A...)(ErrorInfo error, in Char[] fmt, A args) {
4749
ErrorBegin(error);
@@ -163,6 +165,7 @@ class Compiler {
163165
case NodeType.Enum: backend.CompileEnum(cast(EnumNode) inode); break;
164166
case NodeType.Union: backend.CompileUnion(cast(UnionNode) inode); break;
165167
case NodeType.Alias: backend.CompileAlias(cast(AliasNode) inode); break;
168+
case NodeType.Extern: backend.CompileExtern(cast(ExternNode) inode); break;
166169
default: {
167170
backend.Error(inode.error, "Unimplemented node '%s'", inode.type);
168171
}
@@ -192,7 +195,8 @@ class Compiler {
192195
case NodeType.Const:
193196
case NodeType.Enum:
194197
case NodeType.Union:
195-
case NodeType.Alias: {
198+
case NodeType.Alias:
199+
case NodeType.Extern: {
196200
header ~= node;
197201
break;
198202
}

source/lexer.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class Lexer {
5252
't': '\t',
5353
'e': '\x1b',
5454
'"': '"',
55-
'\\': '\\'
55+
'\\': '\\',
56+
'0': '\0'
5657
];
5758
}
5859

source/parser.d

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ enum NodeType {
2828
Enum,
2929
Restrict,
3030
Union,
31-
Alias
31+
Alias,
32+
Extern
3233
}
3334

3435
class Node {
@@ -397,6 +398,18 @@ class AliasNode : Node {
397398
override string toString() => format("alias %s %s", to, from);
398399
}
399400

401+
class ExternNode : Node {
402+
string func;
403+
bool raw;
404+
405+
this(ErrorInfo perror) {
406+
type = NodeType.Extern;
407+
error = perror;
408+
}
409+
410+
override string toString() => format("extern %s%s", raw? "" : "raw ", func);
411+
}
412+
400413
class ParserError : Exception {
401414
this() {
402415
super("", "", 0);
@@ -926,6 +939,25 @@ class Parser {
926939
return ret;
927940
}
928941

942+
Node ParseExtern() {
943+
auto ret = new ExternNode(GetError());
944+
parsing = NodeType.Extern;
945+
946+
Next();
947+
Expect(TokenType.Identifier);
948+
949+
if (tokens[i].contents == "raw") {
950+
ret.raw = true;
951+
952+
Next();
953+
Expect(TokenType.Identifier);
954+
}
955+
956+
ret.func = tokens[i].contents;
957+
958+
return ret;
959+
}
960+
929961
Node ParseStatement() {
930962
switch (tokens[i].type) {
931963
case TokenType.Integer: {
@@ -949,6 +981,7 @@ class Parser {
949981
case "restrict": return ParseRestrict();
950982
case "union": return ParseUnion();
951983
case "alias": return ParseAlias();
984+
case "extern": return ParseExtern();
952985
default: return new WordNode(GetError(), tokens[i].contents);
953986
}
954987
}

0 commit comments

Comments
 (0)