Skip to content

Commit f436968

Browse files
committed
Merge branch 'release/0.41.6'
2 parents 4508c78 + 5f2ada6 commit f436968

File tree

7 files changed

+49
-14
lines changed

7 files changed

+49
-14
lines changed

build/ultratiny.flx

-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,6 @@ class B : A
109109
}
110110

111111

112-
113-
114112
@entry fn main()
115113
{
116114
fn foo(x: int = 3, y: int = 7) -> int => x * y

makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ CFLAGS += -std=c11 -O0 -g -c -Wall -fno-omit-frame-pointer -Wno-overlength-str
4646

4747
LDFLAGS += $(SANITISE)
4848

49-
FLXFLAGS += -sysroot $(SYSROOT)
49+
FLXFLAGS += -sysroot $(SYSROOT) --ffi-escape
5050

5151

5252
SUPERTINYBIN := build/supertiny

source/fir/interp/interpreter.cpp

+27-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "ir/function.h"
1010
#include "ir/instruction.h"
1111

12+
#include "frontend.h"
1213
#include "gluecode.h"
1314
#include "platform.h"
1415

@@ -918,11 +919,32 @@ namespace interp
918919

919920

920921

922+
static void complainAboutFFIEscape(void* fnptr, fir::Type* fnty, const std::string& name)
923+
{
924+
if(frontend::getCanFFIEscape())
925+
return;
921926

927+
BareError* e = 0;
928+
if(name.empty())
929+
{
930+
e = BareError::make("interp: cannot call external function (name unavailable; symbol address %p, function type '%s')",
931+
fnptr, fnty->str());
932+
}
933+
else
934+
{
935+
e = BareError::make("interp: cannot call external function '%s'", name);
936+
}
937+
938+
e->append(BareError::make(MsgType::Note, "to call external functions (ffi), pass '--ffi-escape' as a command-line flag"));
939+
e->postAndQuit();
940+
}
922941

923942

924-
static interp::Value runFunctionWithLibFFI(InterpState* is, void* fnptr, fir::FunctionType* fnty, const std::vector<interp::Value>& args)
943+
static interp::Value runFunctionWithLibFFI(InterpState* is, void* fnptr, fir::FunctionType* fnty, const std::vector<interp::Value>& args,
944+
const std::string& nameIfAvailable = "")
925945
{
946+
complainAboutFFIEscape(fnptr, fnty, nameIfAvailable);
947+
926948
// we are assuming the values in 'args' are correct!
927949
ffi_type** arg_types = new ffi_type*[args.size()];
928950
{
@@ -998,15 +1020,15 @@ namespace interp
9981020
void* fnptr = platform::compiler::getSymbol(fn->getName().str());
9991021
if(!fnptr) error("interp: failed to find symbol named '%s'\n", fn->getName().str());
10001022

1001-
return runFunctionWithLibFFI(is, fnptr, fn->getType(), args);
1023+
return runFunctionWithLibFFI(is, fnptr, fn->getType(), args, /* name: */ fn->getName().str());
10021024
}
10031025

10041026
static interp::Value runFunctionWithLibFFI(InterpState* is, const interp::Function& fn, const std::vector<interp::Value>& args)
10051027
{
10061028
void* fnptr = platform::compiler::getSymbol(fn.func->getName().str());
10071029
if(!fnptr) error("interp: failed to find symbol named '%s'\n", fn.func->getName().str());
10081030

1009-
return runFunctionWithLibFFI(is, fnptr, fn.func->getType(), args);
1031+
return runFunctionWithLibFFI(is, fnptr, fn.func->getType(), args, /* name: */ fn.extFuncName);
10101032
}
10111033

10121034

@@ -1134,7 +1156,8 @@ namespace interp
11341156
else
11351157
error("interp: call to function pointer with invalid type '%s'", targ.type);
11361158

1137-
is->stackFrames.back().values[res.callResultValue] = runFunctionWithLibFFI(is, (void*) ptr, fnty, res.callArguments);
1159+
is->stackFrames.back().values[res.callResultValue] = runFunctionWithLibFFI(is, (void*) ptr, fnty, res.callArguments,
1160+
/* name: */ res.callTarget->extFuncName);
11381161
i += 1;
11391162
}
11401163
} break;

source/frontend/arguments.cpp

+15-4
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@
3232
#define ARG_SHOW_CLANG_OUTPUT "-show-clang"
3333
#define ARG_SYSROOT "-sysroot"
3434
#define ARG_TARGET "-target"
35-
#define ARG_FREESTANDING "-ffreestanding"
36-
#define ARG_NOSTDLIB "-nostdlib"
37-
#define ARG_NO_RUNTIME_CHECKS "-no-runtime-checks"
38-
#define ARG_NO_RUNTIME_ERROR_STRINGS "-no-runtime-error-strings"
35+
#define ARG_FFI_ESCAPE "--ffi-escape"
36+
#define ARG_FREESTANDING "--freestanding"
37+
#define ARG_NOSTDLIB "--nostdlib"
38+
#define ARG_NO_RUNTIME_CHECKS "--no-runtime-checks"
39+
#define ARG_NO_RUNTIME_ERROR_STRINGS "--no-runtime-error-strings"
3940

4041
// for internal use!
4142
#define ARG_ABORT_ON_ERROR "-abort-on-error"
@@ -72,6 +73,7 @@ static void setupMap()
7273

7374
list.push_back({ ARG_FREESTANDING, "generate a freestanding executable or object file" });
7475
list.push_back({ ARG_NOSTDLIB, "do not link with default libraries (libc/libm/msvcrt)" });
76+
list.push_back({ ARG_FFI_ESCAPE, "allow calling external functions (eg. libc) at compile-time" });
7577

7678
list.push_back({ ARG_POSINDEPENDENT, "generate position independent code" });
7779
list.push_back({ ARG_PRINT_FIR, "print the FlaxIR before compilation" });
@@ -171,6 +173,7 @@ namespace frontend
171173
bool _noStandardLibraries = false;
172174
bool _noAutoGlobalConstructor = false;
173175
bool _abortOnError = false;
176+
bool _ffiEscape = false;
174177

175178
bool _noRuntimeChecks = false;
176179
bool _noRuntimeErrorStrings = false;
@@ -223,6 +226,10 @@ namespace frontend
223226
return _abortOnError;
224227
}
225228

229+
bool getCanFFIEscape()
230+
{
231+
return _ffiEscape;
232+
}
226233

227234
bool getPrintFIR()
228235
{
@@ -436,6 +443,10 @@ namespace frontend
436443
{
437444
frontend::_noRuntimeErrorStrings = true;
438445
}
446+
else if(!strcmp(argv[i], ARG_FFI_ESCAPE))
447+
{
448+
frontend::_ffiEscape = true;
449+
}
439450
else if(!strcmp(argv[i], ARG_BACKEND))
440451
{
441452
if(i != argc - 1)

source/include/frontend.h

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace frontend
4848
bool getPrintProfileStats();
4949
bool getAbortOnError();
5050

51+
bool getCanFFIEscape();
5152
bool getIsFreestanding();
5253
bool getIsNoStandardLibraries();
5354
bool getIsPositionIndependent();

source/include/utils.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,8 @@ namespace util
195195
template <typename T, typename U>
196196
std::vector<std::pair<T, U>> zip(const std::vector<T>& a, const std::vector<U>& b)
197197
{
198-
assert(a.size() == b.size());
199-
200198
std::vector<std::pair<T, U>> ret;
201-
for(size_t i = 0; i < a.size(); i++)
199+
for(size_t i = 0; i < std::min(a.size(), b.size()); i++)
202200
ret.push_back({ a[i], b[i] });
203201

204202
return ret;

source/typecheck/classes.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ TCResult ast::ClassDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type*
4848
auto cls = fir::ClassType::createWithoutBody(defn->id);
4949
defn->type = cls;
5050

51+
52+
// why do we do this when generating the declaration instead of only when we typecheck?
53+
// as it currently stands, this means that our base class + any traits must appear before
54+
// this class definition in the source code, which is kinda dumb.
5155
if(this->bases.size() > 0)
5256
{
5357
auto base = fs->convertParserTypeToFIR(this->bases[0]);

0 commit comments

Comments
 (0)