Exemple #1
0
    bool GetFields( RecordDecl * rd, Obj * entries) {
     
        //check the fields of this struct, if any one of them is not understandable, then this struct becomes 'opaque'
        //that is, we insert the type, and link it to its llvm type, so it can be used in terra code
        //but none of its fields are exposed (since we don't understand the layout)
        bool opaque = false;
        for(RecordDecl::field_iterator it = rd->field_begin(), end = rd->field_end(); it != end; ++it) {
            if(it->isBitField() || it->isAnonymousStructOrUnion() || !it->getDeclName()) {
                opaque = true;
                continue;
            }
            DeclarationName declname = it->getDeclName();
            std::string declstr = declname.getAsString();
            QualType FT = it->getType();
            Obj fobj;
            if(!GetType(FT,&fobj)) {
                opaque = true;
                continue;
            }
            lua_newtable(L);
            fobj.push();
            lua_setfield(L,-2,"type");
            lua_pushstring(L,declstr.c_str());
            lua_setfield(L,-2,"field");
            entries->addentry();
        }
        return !opaque;

    }
Exemple #2
0
 bool GetFuncType(const FunctionType * f, Obj * typ) {
     Obj returns,parameters;
     resulttable->newlist(&returns);
     resulttable->newlist(&parameters);
     
     bool valid = true; //decisions about whether this function can be exported or not are delayed until we have seen all the potential problems
     QualType RT = f->getResultType();
     if(!RT->isVoidType()) {
         Obj rt;
         if(!GetType(RT,&rt)) {
             valid = false;
         } else {
             rt.push();
             returns.addentry();
         }
     }
    
     
     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) {
         for(size_t i = 0; i < proto->getNumArgs(); i++) {
             QualType PT = proto->getArgType(i);
             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) {
         PushTypeFunction("functype");
         parameters.push();
         returns.push();
         lua_pushboolean(L, proto ? proto->isVariadic() : false);
         lua_call(L, 3, 1);
         typ->initFromStack(L,ref_table);
     }
     
     return valid;
 }
Exemple #3
0
 bool VisitTypedefDecl(TypedefDecl * TD) {
     if(TD == TD->getCanonicalDecl() && TD->getDeclContext()->getDeclKind() == Decl::TranslationUnit) {
         llvm::StringRef name = TD->getName();
         QualType QT = Context->getCanonicalType(TD->getUnderlyingType());
         Obj typ;
         if(GetType(QT,&typ)) {
             typ.push();
             general.setfield(name.str().c_str());
         } else {
             SetErrorReport(name.str().c_str());
         }
     }
     return true;
 }
Exemple #4
0
 bool GetFuncType(const FunctionType * f, Obj * typ) {
     Obj returntype,parameters;
     resulttable->newlist(&parameters);
     
     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;
 }
Exemple #5
0
 bool GetType(QualType T, Obj * tt) {
     
     T = Context->getCanonicalType(T);
     const Type *Ty = T.getTypePtr();
     
     switch (Ty->getTypeClass()) {
       case Type::Record: {
         const RecordType *RT = dyn_cast<RecordType>(Ty);
         RecordDecl * rd = RT->getDecl();
         return GetRecordTypeFromDecl(rd, tt);
       }  break; //TODO
       case Type::Builtin:
         switch (cast<BuiltinType>(Ty)->getKind()) {
         case BuiltinType::Void:
           InitType("opaque",tt);
             return true;
         case BuiltinType::Bool:
             InitType("bool",tt);
             return true;
         case BuiltinType::Char_S:
         case BuiltinType::Char_U:
         case BuiltinType::SChar:
         case BuiltinType::UChar:
         case BuiltinType::Short:
         case BuiltinType::UShort:
         case BuiltinType::Int:
         case BuiltinType::UInt:
         case BuiltinType::Long:
         case BuiltinType::ULong:
         case BuiltinType::LongLong:
         case BuiltinType::ULongLong:
         case BuiltinType::WChar_S:
         case BuiltinType::WChar_U:
         case BuiltinType::Char16:
         case BuiltinType::Char32: {
             std::stringstream ss;
             if (Ty->isUnsignedIntegerType())
                 ss << "u";
             ss << "int";
             int sz = Context->getTypeSize(T);
             ss << sz;
             InitType(ss.str().c_str(),tt);
             return true;
         }
         case BuiltinType::Half:
             break;
         case BuiltinType::Float:
             InitType("float",tt);
             return true;
         case BuiltinType::Double:
             InitType("double",tt);
             return true;
         case BuiltinType::LongDouble:
         case BuiltinType::NullPtr:
         case BuiltinType::UInt128:
         default:
             break;
         }
       case Type::Complex:
       case Type::LValueReference:
       case Type::RValueReference:
         break;
       case Type::Pointer: {
         const PointerType *PTy = cast<PointerType>(Ty);
         QualType ETy = PTy->getPointeeType();
         Obj t2;
         if(!GetType(ETy,&t2)) {
             return false;
         }
         PushTypeField("pointer");
         t2.push();
         lua_call(L,1,1);
         tt->initFromStack(L, ref_table);
         return true;
       }
       
       case Type::VariableArray:
       case Type::IncompleteArray:
         break;
       case Type::ConstantArray: {
         Obj at;
         const ConstantArrayType *ATy = cast<ConstantArrayType>(Ty);
         int sz = ATy->getSize().getZExtValue();
         if(GetType(ATy->getElementType(),&at)) {
             PushTypeField("array");
             at.push();
             lua_pushinteger(L, sz);
             lua_call(L,2,1);
             tt->initFromStack(L,ref_table);
             return true;
         } else {
             return false;
         }
       } break;
       case Type::ExtVector:
       case Type::Vector: {
             //printf("making a vector!\n");
             const VectorType *VT = cast<VectorType>(T);
             Obj at;
             if(GetType(VT->getElementType(),&at)) {
                 int n = VT->getNumElements();
                 PushTypeField("vector");
                 at.push();
                 lua_pushinteger(L,n);
                 lua_call(L,2,1);
                 tt->initFromStack(L, ref_table);
                 return true;
             } else {
                 return false;
             }
       } break;
       case Type::FunctionNoProto:
             break;
       case Type::FunctionProto: {
             const FunctionProtoType *FT = cast<FunctionProtoType>(Ty);
             //call functype... getNumArgs();
             if(FT && GetFuncType(FT,tt))
                 return true;
             else
                 return false;
             break;
       }
       case Type::ObjCObject:
       case Type::ObjCInterface:
       case Type::ObjCObjectPointer:
       case Type::Enum:
         InitType("uint32",tt);
         return true;
       case Type::BlockPointer:
       case Type::MemberPointer:
       case Type::Atomic:
       default:
         break;
     }
     std::stringstream ss;
     ss << "type not understood: " << T.getAsString().c_str() << " " << Ty->getTypeClass();
     return ImportError(ss.str().c_str());
 }
Exemple #6
0
 bool GetRecordTypeFromDecl(RecordDecl * rd, Obj * tt) {
     if(rd->isStruct() || rd->isUnion()) {
         std::string name = rd->getName();
         Obj * thenamespace = &tagged;
         if(name == "") {
             TypedefNameDecl * decl = rd->getTypedefNameForAnonDecl();
             if(decl) {
                 thenamespace = &general;
                 name = decl->getName();
             }
         }
         //if name == "" then we have an anonymous struct
         if(!thenamespace->obj(name.c_str(),tt)) {
             PushTypeField("getorcreatecstruct");
             lua_pushstring(L, name.c_str());
             lua_pushboolean(L, thenamespace == &tagged);
             lua_call(L,2,1);
             tt->initFromStack(L,ref_table);
             if(!tt->boolean("llvm_definingfunction")) {
                 std::string definingfunction;
                 size_t argpos;
                 RegisterRecordType(Context->getRecordType(rd), &definingfunction, &argpos);
                 lua_pushstring(L,definingfunction.c_str());
                 tt->setfield("llvm_definingfunction");
                 lua_pushinteger(L,argpos);
                 tt->setfield("llvm_argumentposition");
             }
             if(name != "") { //do not remember a name for an anonymous struct
                 tt->push();
                 thenamespace->setfield(name.c_str()); //register the type
             }
         }
         
         if(tt->boolean("undefined") && rd->getDefinition() != NULL) {
             tt->clearfield("undefined");
             RecordDecl * defn = rd->getDefinition();
             Obj entries;
             tt->newlist(&entries);
             if(GetFields(defn, &entries)) {
                 if(!defn->isUnion()) {
                     //structtype.entries = {entry1, entry2, ... }
                     entries.push();
                     tt->setfield("entries");
                 } else {
                     //add as a union:
                     //structtype.entries = { {entry1,entry2,...} }
                     Obj allentries;
                     tt->obj("entries",&allentries);
                     entries.push();
                     allentries.addentry();
                 }
                 tt->pushfield("complete");
                 tt->push();
                 lua_call(L,1,0);
             }
         }
         
         return true;
     } else {
         return ImportError("non-struct record types are not supported");
     }
 }
Exemple #7
0
    bool GetRecordTypeFromDecl(RecordDecl * rd, Obj * tt, std::string * fullname) {
        if(rd->isStruct() || rd->isUnion()) {
            std::string name = rd->getName();
            //TODO: why do some types not have names?
            Obj * thenamespace = &tagged;
            if(name == "") {
                TypedefNameDecl * decl = rd->getTypedefNameForAnonDecl();
                if(decl) {
                    thenamespace = &general;
                    name = decl->getName();
                } else {
                    name = "anon";
                }
            }

            assert(name != "");

            if(!thenamespace->obj(name.c_str(),tt)) {
                //create new blank struct, fill in with members
                std::stringstream ss;
                ss << (rd->isStruct() ? "struct." : "union.") << name;
                PushTypeFunction("getorcreatecstruct");
                lua_pushstring(L, name.c_str());
                lua_pushstring(L,ss.str().c_str());
                lua_call(L,2,1);
                tt->initFromStack(L,ref_table);
                tt->push();
                thenamespace->setfield(name.c_str()); //register the type (this prevents an infinite loop for recursive types)
            }
            
            if(tt->boolean("undefined") && rd->getDefinition() != NULL) {
                tt->clearfield("undefined");
                RecordDecl * defn = rd->getDefinition();
                Obj entries;
                tt->newlist(&entries);
                if(GetFields(defn, &entries)) {
                    if(!defn->isUnion()) {
                        //structtype.entries = {entry1, entry2, ... }
                        entries.push();
                        tt->setfield("entries");
                    } else {
                        //add as a union:
                        //structtype.entries = { {entry1,entry2,...} }
                        Obj allentries;
                        tt->obj("entries",&allentries);
                        entries.push();
                        allentries.addentry();
                    }
                    tt->pushfield("complete");
                    tt->push();
                    lua_call(L,1,0);
                }
            }
            
            if(fullname) {
                std::stringstream ss;
                if(thenamespace == &tagged)
                    ss << (rd->isStruct() ? "struct " : "union ");
                ss << name;
                *fullname = ss.str();
            }
            
            return true;
        } else {
            return ImportError("non-struct record types are not supported");
        }
    }