bool TraverseFunctionDecl(FunctionDecl *f) { // Function name DeclarationName DeclName = f->getNameInfo().getName(); std::string FuncName = DeclName.getAsString(); const FunctionType * fntyp = f->getType()->getAs<FunctionType>(); if(!fntyp) return true; if(f->getStorageClass() == clang::SC_Static) { ImportError("cannot import static functions."); SetErrorReport(FuncName.c_str()); return true; } Obj typ; if(!GetFuncType(fntyp,&typ)) { SetErrorReport(FuncName.c_str()); return true; } std::string InternalName = FuncName; AsmLabelAttr * asmlabel = f->getAttr<AsmLabelAttr>(); if(asmlabel) { InternalName = asmlabel->getLabel(); #ifndef __linux__ //In OSX and Windows LLVM mangles assembler labels by adding a '\01' prefix InternalName.insert(InternalName.begin(), '\01'); #endif } CreateFunction(FuncName,InternalName,&typ); KeepFunctionLive(f);//make sure this function is live in codegen by creating a dummy reference to it (void) is to suppress unused warnings return true; }
bool GetFuncType(const FunctionType * f, Obj * typ) { Obj returntype,parameters; resulttable->newlist(¶meters); bool valid = true; //decisions about whether this function can be exported or not are delayed until we have seen all the potential problems #if LLVM_VERSION <= 34 QualType RT = f->getResultType(); #else QualType RT = f->getReturnType(); #endif if(RT->isVoidType()) { PushTypeField("unit"); returntype.initFromStack(L, ref_table); } else { if(!GetType(RT,&returntype)) valid = false; } const FunctionProtoType * proto = f->getAs<FunctionProtoType>(); //proto is null if the function was declared without an argument list (e.g. void foo() and not void foo(void)) //we don't support old-style C parameter lists, we just treat them as empty if(proto) { #if LLVM_VERSION >= 35 for(size_t i = 0; i < proto->getNumParams(); i++) { QualType PT = proto->getParamType(i); #else for(size_t i = 0; i < proto->getNumArgs(); i++) { QualType PT = proto->getArgType(i); #endif Obj pt; if(!GetType(PT,&pt)) { valid = false; //keep going with attempting to parse type to make sure we see all the reasons why we cannot support this function } else if(valid) { pt.push(); parameters.addentry(); } } } if(valid) { PushTypeField("functype"); parameters.push(); returntype.push(); lua_pushboolean(L, proto ? proto->isVariadic() : false); lua_call(L, 3, 1); typ->initFromStack(L,ref_table); } return valid; } bool TraverseFunctionDecl(FunctionDecl *f) { // Function name DeclarationName DeclName = f->getNameInfo().getName(); std::string FuncName = DeclName.getAsString(); const FunctionType * fntyp = f->getType()->getAs<FunctionType>(); if(!fntyp) return true; if(f->getStorageClass() == clang::SC_Static) { ImportError("cannot import static functions."); SetErrorReport(FuncName.c_str()); return true; } Obj typ; if(!GetFuncType(fntyp,&typ)) { SetErrorReport(FuncName.c_str()); return true; } std::string InternalName = FuncName; AsmLabelAttr * asmlabel = f->getAttr<AsmLabelAttr>(); if(asmlabel) { InternalName = asmlabel->getLabel(); #ifndef __linux__ //In OSX and Windows LLVM mangles assembler labels by adding a '\01' prefix InternalName.insert(InternalName.begin(), '\01'); #endif } CreateFunction(FuncName,InternalName,&typ); KeepFunctionLive(f);//make sure this function is live in codegen by creating a dummy reference to it (void) is to suppress unused warnings return true; }