Example #1
0
static int
do_assemble(SourceManager& source_mgr, DiagnosticsEngine& diags)
{
    // Apply warning settings
    ApplyWarningSettings(diags);

    // Determine objfmt_bits based on -32 and -64 options
    std::string objfmt_bits = GetBitsSetting();

    FileManager& file_mgr = source_mgr.getFileManager();
    Assembler assembler("x86", YGAS_OBJFMT_BASE + objfmt_bits, diags,
                        dump_object);
    HeaderSearch headers(file_mgr);

    if (diags.hasFatalErrorOccurred())
        return EXIT_FAILURE;

    // Set object filename if specified.
    if (!obj_filename.empty())
        assembler.setObjectFilename(obj_filename);

    // Set parser.
    assembler.setParser("gas", diags);

    if (diags.hasFatalErrorOccurred())
        return EXIT_FAILURE;

    // Set debug format to dwarf2pass if it's legal for this object format.
    if (assembler.isOkDebugFormat("dwarf2pass"))
    {
        assembler.setDebugFormat("dwarf2pass", diags);
        if (diags.hasFatalErrorOccurred())
            return EXIT_FAILURE;
    }

    // open the input file or STDIN (for filename of "-")
    if (in_filename == "-")
    {
        OwningPtr<MemoryBuffer> my_stdin;
        if (llvm::error_code err = MemoryBuffer::getSTDIN(my_stdin))
        {
            diags.Report(SourceLocation(), diag::fatal_file_open)
                << in_filename << err.message();
            return EXIT_FAILURE;
        }
        source_mgr.createMainFileIDForMemBuffer(my_stdin.take());
    }
    else
    {
        const FileEntry* in = file_mgr.getFile(in_filename);
        if (!in)
        {
            diags.Report(SourceLocation(), diag::fatal_file_open)
                << in_filename;
            return EXIT_FAILURE;
        }
        source_mgr.createMainFileID(in);
    }

    // Initialize the object.
    if (!assembler.InitObject(source_mgr, diags))
        return EXIT_FAILURE;

    // Configure object per command line parameters.
    ConfigureObject(*assembler.getObject());

    // Predefine symbols.
    for (std::vector<std::string>::const_iterator i=defsym.begin(),
         end=defsym.end(); i != end; ++i)
    {
        StringRef str(*i);
        size_t equalpos = str.find('=');
        if (equalpos == StringRef::npos)
        {
            diags.Report(diag::fatal_bad_defsym) << str;
            continue;
        }
        StringRef name = str.slice(0, equalpos);
        StringRef vstr = str.slice(equalpos+1, StringRef::npos);

        IntNum value;
        if (!vstr.empty())
        {
            // determine radix
            unsigned int radix;
            if (vstr[0] == '0' && vstr.size() > 1 &&
                (vstr[1] == 'x' || vstr[1] == 'X'))
            {
                vstr = vstr.substr(2);
                radix = 16;
            }
            else if (vstr[0] == '0')
            {
                vstr = vstr.substr(1);
                radix = 8;
            }
            else
                radix = 10;

            // check validity
            const char* ptr = vstr.begin();
            const char* end = vstr.end();
            if (radix == 16)
            {
                while (ptr != end && isxdigit(*ptr))
                    ++ptr;
            }
            else if (radix == 8)
            {
                while (ptr != end && (*ptr >= '0' && *ptr <= '7'))
                    ++ptr;
            }
            else
            {
                while (ptr != end && isdigit(*ptr))
                    ++ptr;
            }
            if (ptr != end)
            {
                diags.Report(diag::fatal_bad_defsym) << name;
                continue;
            }
            value.setStr(vstr, radix);
        }

        // define equ
        assembler.getObject()->getSymbol(name)->DefineEqu(Expr(value));
    }

    if (diags.hasFatalErrorOccurred())
        return EXIT_FAILURE;

    // Initialize the parser.
    assembler.InitParser(source_mgr, diags, headers);

    // Assemble the input.
    if (!assembler.Assemble(source_mgr, diags))
    {
        // An error occurred during assembly.
        return EXIT_FAILURE;
    }

    // open the object file for output
    std::string err;
    raw_fd_ostream out(assembler.getObjectFilename().str().c_str(),
                       err, raw_fd_ostream::F_Binary);
    if (!err.empty())
    {
        diags.Report(SourceLocation(), diag::err_cannot_open_file)
            << obj_filename << err;
        return EXIT_FAILURE;
    }

    if (!assembler.Output(out, diags))
    {
        // An error occurred during output.
        // If we had an error at this point, we also need to delete the output
        // object file (to make sure it's not left newer than the source).
        out.close();
        remove(assembler.getObjectFilename().str().c_str());
        return EXIT_FAILURE;
    }

    // close object file
    out.close();
    return EXIT_SUCCESS;
}