@@ -11,10 +11,20 @@ import callisto.parser;
1111import callisto.compiler;
1212import callisto.language;
1313
14+ private enum WordType {
15+ Callisto,
16+ Raw,
17+ C
18+ }
19+
1420private struct Word {
15- bool raw;
16- bool inline;
17- Node[] inlineNodes;
21+ WordType type;
22+ bool inline;
23+ Node[] inlineNodes;
24+
25+ // for C words
26+ Type[] params;
27+ Type* ret;
1828}
1929
2030private struct StructEntry {
@@ -312,9 +322,43 @@ class BackendLinux86 : CompilerBackend {
312322 }
313323 }
314324 else {
315- if (word.raw ) {
325+ if (word.type == WordType.Raw ) {
316326 output ~= format(" call %s\n " , node.name);
317327 }
328+ else if (word.type == WordType.C) {
329+ if (word.params.length >= 1 ) {
330+ output ~= " sub r15, 8\n " ;
331+ output ~= " mov rdi, [r15]\n " ;
332+ }
333+ if (word.params.length >= 2 ) {
334+ output ~= " sub r15, 8\n " ;
335+ output ~= " mov rsi, [r15]\n " ;
336+ }
337+ if (word.params.length >= 3 ) {
338+ output ~= " sub r15, 8\n " ;
339+ output ~= " mov rdx, [r15]\n " ;
340+ }
341+ if (word.params.length >= 4 ) {
342+ output ~= " sub r15, 8\n " ;
343+ output ~= " mov rcx, [r15]\n " ;
344+ }
345+ if (word.params.length >= 5 ) {
346+ output ~= " sub r15, 8\n " ;
347+ output ~= " mov r8, [r15]\n " ;
348+ }
349+ if (word.params.length >= 6 ) {
350+ output ~= " sub r15, 8\n " ;
351+ output ~= " mov r9, [r15]\n " ;
352+ }
353+
354+
355+ output ~= format(" call %s\n " , node.name);
356+
357+ if (word.ret ! is null ) {
358+ output ~= " mov [r15], rax\n " ;
359+ output ~= " add r15, 8\n " ;
360+ }
361+ }
318362 else {
319363 output ~= format(" call __func__%s\n " , node.name.Sanitise());
320364 }
@@ -368,13 +412,13 @@ class BackendLinux86 : CompilerBackend {
368412 thisFunc = node.name;
369413
370414 if (node.inline) {
371- words[node.name] = Word(false , true , node.nodes);
415+ words[node.name] = Word(WordType.Callisto , true , node.nodes);
372416 }
373417 else {
374418 assert (! inScope);
375419 inScope = true ;
376420
377- words[node.name] = Word(node.raw, false , []);
421+ words[node.name] = Word(node.raw? WordType.Raw : WordType.Callisto , false , []);
378422
379423 string symbol =
380424 node.raw? node.name : format(" __func__%s" , node.name.Sanitise());
@@ -785,12 +829,37 @@ class BackendLinux86 : CompilerBackend {
785829
786830 override void CompileExtern (ExternNode node) {
787831 Word word;
788- word.raw = node.raw;
789- words[node.func] = word;
790832
791- if (word.raw) {
833+ final switch (node.externType) {
834+ case ExternType.Callisto: word.type = WordType.Callisto; break ;
835+ case ExternType.Raw: word.type = WordType.Raw; break ;
836+ case ExternType.C: {
837+ word.type = WordType.C;
838+
839+ foreach (ref param ; node.types) {
840+ if (param ! in types) {
841+ Error(node.error, " Unknown type '%s'" , param);
842+ }
843+
844+ word.params ~= types[param];
845+ }
846+
847+ if (node.retType != " void" ) {
848+ if (node.retType ! in types) {
849+ Error(node.error, " Unknown type '%s'" , node.retType);
850+ }
851+
852+ word.ret = node.retType in types;
853+ }
854+ break ;
855+ }
856+ }
857+
858+ if (word.type != WordType.Callisto) {
792859 output ~= format(" extern %s\n " , node.func);
793860 }
861+
862+ words[node.func] = word;
794863 }
795864
796865 override void CompileCall (WordNode node) {
@@ -805,7 +874,8 @@ class BackendLinux86 : CompilerBackend {
805874 }
806875
807876 auto word = words[node.func];
808- string symbol = word.raw? node.func : format(" __func__%s" , node.func.Sanitise());
877+ string symbol = word.type == WordType.Callisto?
878+ format(" __func__%s" , node.func.Sanitise()) : node.func;
809879
810880 output ~= format(" mov rax, %s\n " , symbol);
811881 output ~= " mov [r15], rax\n " ;
0 commit comments