Skip to content

Commit

Permalink
Merge branch 'release/0.41.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiayang committed Oct 12, 2019
2 parents 4508c78 + 5f2ada6 commit f436968
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 14 deletions.
2 changes: 0 additions & 2 deletions build/ultratiny.flx
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ class B : A
}




@entry fn main()
{
fn foo(x: int = 3, y: int = 7) -> int => x * y
Expand Down
2 changes: 1 addition & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ CFLAGS += -std=c11 -O0 -g -c -Wall -fno-omit-frame-pointer -Wno-overlength-str

LDFLAGS += $(SANITISE)

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


SUPERTINYBIN := build/supertiny
Expand Down
31 changes: 27 additions & 4 deletions source/fir/interp/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "ir/function.h"
#include "ir/instruction.h"

#include "frontend.h"
#include "gluecode.h"
#include "platform.h"

Expand Down Expand Up @@ -918,11 +919,32 @@ namespace interp



static void complainAboutFFIEscape(void* fnptr, fir::Type* fnty, const std::string& name)
{
if(frontend::getCanFFIEscape())
return;

BareError* e = 0;
if(name.empty())
{
e = BareError::make("interp: cannot call external function (name unavailable; symbol address %p, function type '%s')",
fnptr, fnty->str());
}
else
{
e = BareError::make("interp: cannot call external function '%s'", name);
}

e->append(BareError::make(MsgType::Note, "to call external functions (ffi), pass '--ffi-escape' as a command-line flag"));
e->postAndQuit();
}


static interp::Value runFunctionWithLibFFI(InterpState* is, void* fnptr, fir::FunctionType* fnty, const std::vector<interp::Value>& args)
static interp::Value runFunctionWithLibFFI(InterpState* is, void* fnptr, fir::FunctionType* fnty, const std::vector<interp::Value>& args,
const std::string& nameIfAvailable = "")
{
complainAboutFFIEscape(fnptr, fnty, nameIfAvailable);

// we are assuming the values in 'args' are correct!
ffi_type** arg_types = new ffi_type*[args.size()];
{
Expand Down Expand Up @@ -998,15 +1020,15 @@ namespace interp
void* fnptr = platform::compiler::getSymbol(fn->getName().str());
if(!fnptr) error("interp: failed to find symbol named '%s'\n", fn->getName().str());

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

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

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


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

is->stackFrames.back().values[res.callResultValue] = runFunctionWithLibFFI(is, (void*) ptr, fnty, res.callArguments);
is->stackFrames.back().values[res.callResultValue] = runFunctionWithLibFFI(is, (void*) ptr, fnty, res.callArguments,
/* name: */ res.callTarget->extFuncName);
i += 1;
}
} break;
Expand Down
19 changes: 15 additions & 4 deletions source/frontend/arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
#define ARG_SHOW_CLANG_OUTPUT "-show-clang"
#define ARG_SYSROOT "-sysroot"
#define ARG_TARGET "-target"
#define ARG_FREESTANDING "-ffreestanding"
#define ARG_NOSTDLIB "-nostdlib"
#define ARG_NO_RUNTIME_CHECKS "-no-runtime-checks"
#define ARG_NO_RUNTIME_ERROR_STRINGS "-no-runtime-error-strings"
#define ARG_FFI_ESCAPE "--ffi-escape"
#define ARG_FREESTANDING "--freestanding"
#define ARG_NOSTDLIB "--nostdlib"
#define ARG_NO_RUNTIME_CHECKS "--no-runtime-checks"
#define ARG_NO_RUNTIME_ERROR_STRINGS "--no-runtime-error-strings"

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

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

list.push_back({ ARG_POSINDEPENDENT, "generate position independent code" });
list.push_back({ ARG_PRINT_FIR, "print the FlaxIR before compilation" });
Expand Down Expand Up @@ -171,6 +173,7 @@ namespace frontend
bool _noStandardLibraries = false;
bool _noAutoGlobalConstructor = false;
bool _abortOnError = false;
bool _ffiEscape = false;

bool _noRuntimeChecks = false;
bool _noRuntimeErrorStrings = false;
Expand Down Expand Up @@ -223,6 +226,10 @@ namespace frontend
return _abortOnError;
}

bool getCanFFIEscape()
{
return _ffiEscape;
}

bool getPrintFIR()
{
Expand Down Expand Up @@ -436,6 +443,10 @@ namespace frontend
{
frontend::_noRuntimeErrorStrings = true;
}
else if(!strcmp(argv[i], ARG_FFI_ESCAPE))
{
frontend::_ffiEscape = true;
}
else if(!strcmp(argv[i], ARG_BACKEND))
{
if(i != argc - 1)
Expand Down
1 change: 1 addition & 0 deletions source/include/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace frontend
bool getPrintProfileStats();
bool getAbortOnError();

bool getCanFFIEscape();
bool getIsFreestanding();
bool getIsNoStandardLibraries();
bool getIsPositionIndependent();
Expand Down
4 changes: 1 addition & 3 deletions source/include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,8 @@ namespace util
template <typename T, typename U>
std::vector<std::pair<T, U>> zip(const std::vector<T>& a, const std::vector<U>& b)
{
assert(a.size() == b.size());

std::vector<std::pair<T, U>> ret;
for(size_t i = 0; i < a.size(); i++)
for(size_t i = 0; i < std::min(a.size(), b.size()); i++)
ret.push_back({ a[i], b[i] });

return ret;
Expand Down
4 changes: 4 additions & 0 deletions source/typecheck/classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ TCResult ast::ClassDefn::generateDeclaration(sst::TypecheckState* fs, fir::Type*
auto cls = fir::ClassType::createWithoutBody(defn->id);
defn->type = cls;


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

0 comments on commit f436968

Please sign in to comment.