- enhancement: Add "Generate Assembly" in "Run" Menu

- enhancement: Improve highlighter for asm
This commit is contained in:
Roy Qu 2022-12-01 22:10:44 +08:00
parent 164d766c75
commit f9fb966c38
23 changed files with 821 additions and 664 deletions

View File

@ -15,6 +15,8 @@ Red Panda C++ Version 2.5
- fix: Can't correctly show completion suggest for type with template parameters
- enhancement: Show compltion suggest for std::pair::first and std::pair second
- enhancement: Disable "run" and "debug" actions when current project is static or dynamic library
- enhancement: Add "Generate Assembly" in "Run" Menu
- enhancement: Improve highlighter for asm
Red Panda C++ Version 2.4

View File

@ -19,6 +19,13 @@
#include <QString>
#include <memory>
#include <QMetaType>
enum class CppCompileType {
Normal,
PreprocessOnly,
GenerateAssemblyOnly
};
enum class CompileIssueType {
Other,
Warning,

View File

@ -71,7 +71,7 @@ bool CompilerManager::running()
return (mRunner!=nullptr && !mRunner->pausing());
}
void CompilerManager::compile(const QString& filename, const QByteArray& encoding, bool rebuild, bool silent, bool onlyCheckSyntax)
void CompilerManager::compile(const QString& filename, const QByteArray& encoding, bool rebuild, CppCompileType compileType)
{
if (!pSettings->compilerSets().defaultSet()) {
QMessageBox::critical(pMainWindow,
@ -87,7 +87,7 @@ void CompilerManager::compile(const QString& filename, const QByteArray& encodin
mCompileErrorCount = 0;
mCompileIssueCount = 0;
//deleted when thread finished
mCompiler = new FileCompiler(filename,encoding,silent,onlyCheckSyntax);
mCompiler = new FileCompiler(filename,encoding,compileType,false,false);
mCompiler->setRebuild(rebuild);
connect(mCompiler, &Compiler::finished, mCompiler, &QObject::deleteLater);
connect(mCompiler, &Compiler::compileFinished, this, &CompilerManager::onCompileFinished);
@ -102,7 +102,7 @@ void CompilerManager::compile(const QString& filename, const QByteArray& encodin
}
}
void CompilerManager::compileProject(std::shared_ptr<Project> project, bool rebuild, bool silent,bool onlyCheckSyntax)
void CompilerManager::compileProject(std::shared_ptr<Project> project, bool rebuild)
{
if (!pSettings->compilerSets().defaultSet()) {
QMessageBox::critical(pMainWindow,
@ -118,7 +118,7 @@ void CompilerManager::compileProject(std::shared_ptr<Project> project, bool rebu
mCompileErrorCount = 0;
mCompileIssueCount = 0;
//deleted when thread finished
mCompiler = new ProjectCompiler(project,silent,onlyCheckSyntax);
mCompiler = new ProjectCompiler(project,false,false);
mCompiler->setRebuild(rebuild);
connect(mCompiler, &Compiler::finished, mCompiler, &QObject::deleteLater);
connect(mCompiler, &Compiler::compileFinished, this, &CompilerManager::onCompileFinished);

View File

@ -23,8 +23,8 @@
#include "../common.h"
class Runner;
class Compiler;
class Project;
class Compiler;
struct OJProblemCase;
using POJProblemCase = std::shared_ptr<OJProblemCase>;
class CompilerManager : public QObject
@ -37,8 +37,8 @@ public:
bool backgroundSyntaxChecking();
bool running();
void compile(const QString& filename, const QByteArray& encoding, bool rebuild, bool silent=false,bool onlyCheckSyntax=false);
void compileProject(std::shared_ptr<Project> project, bool rebuild, bool silent=false,bool onlyCheckSyntax=false);
void compile(const QString& filename, const QByteArray& encoding, bool rebuild, CppCompileType compileType);
void compileProject(std::shared_ptr<Project> project, bool rebuild);
void cleanProject(std::shared_ptr<Project> project);
void buildProjectMakefile(std::shared_ptr<Project> project);
void checkSyntax(const QString&filename, const QByteArray& encoding, const QString& content, std::shared_ptr<Project> project);

View File

@ -24,15 +24,33 @@
#include <QMessageBox>
FileCompiler::FileCompiler(const QString &filename, const QByteArray &encoding,bool silent,bool onlyCheckSyntax):
FileCompiler::FileCompiler(const QString &filename, const QByteArray &encoding,
CppCompileType compileType,bool silent,bool onlyCheckSyntax):
Compiler(filename, silent,onlyCheckSyntax),
mEncoding(encoding)
mEncoding(encoding),
mCompileType(compileType)
{
}
bool FileCompiler::prepareForCompile()
{
Settings::CompilerSet::CompilationStage oldStage = compilerSet()->compilationStage();
auto action = finally([this,oldStage]{
compilerSet()->setCompilationStage(oldStage);
});
Settings::CompilerSet::CompilationStage stage = oldStage;
switch(mCompileType) {
case CppCompileType::PreprocessOnly:
stage = Settings::CompilerSet::CompilationStage::PreprocessingOnly;
break;
case CppCompileType::GenerateAssemblyOnly:
stage = Settings::CompilerSet::CompilationStage::CompilationProperOnly;
break;
default:
stage = oldStage;
}
compilerSet()->setCompilationStage(stage);
log(tr("Compiling single file..."));
log("------------------");
log(tr("- Filename: %1").arg(mFilename));

View File

@ -23,15 +23,17 @@ class FileCompiler : public Compiler
{
Q_OBJECT
public:
FileCompiler(const QString& filename, const QByteArray& encoding,bool silent,bool onlyCheckSyntax);
FileCompiler(const QString& filename, const QByteArray& encoding,
CppCompileType compileType,
bool silent,bool onlyCheckSyntax);
// Compiler interface
protected:
bool prepareForCompile() override;
private:
QByteArray mEncoding;
CppCompileType mCompileType;
// Compiler interface
protected:
bool prepareForRebuild() override;

View File

@ -4729,7 +4729,9 @@ void Editor::applySettings()
options.setFlag(QSynedit::eoScrollByOneLess,pSettings->editor().scrollByOneLess());
options.setFlag(QSynedit::eoHalfPageScroll,pSettings->editor().halfPageScroll());
options.setFlag(QSynedit::eoHalfPageScroll,pSettings->editor().halfPageScroll());
options.setFlag(QSynedit::eoShowRainbowColor, pSettings->editor().rainbowParenthesis());
options.setFlag(QSynedit::eoShowRainbowColor,
pSettings->editor().rainbowParenthesis()
&& highlighter() && highlighter()->supportBraceLevel());
setOptions(options);
setTabWidth(pSettings->editor().tabWidth());
@ -4818,7 +4820,9 @@ static QSynedit::PHighlighterAttribute createRainbowAttribute(const QString& att
void Editor::applyColorScheme(const QString& schemeName)
{
QSynedit::EditorOptions options = getOptions();
options.setFlag(QSynedit::EditorOption::eoShowRainbowColor, pSettings->editor().rainbowParenthesis());
options.setFlag(QSynedit::EditorOption::eoShowRainbowColor,
pSettings->editor().rainbowParenthesis()
&& highlighter() && highlighter()->supportBraceLevel());
setOptions(options);
highlighterManager.applyColorScheme(highlighter(),schemeName);
if (pSettings->editor().rainbowParenthesis()) {

View File

@ -674,6 +674,7 @@ void MainWindow::updateCompileActions()
ui->actionCompile_Run->setEnabled(false);
ui->actionRun->setEnabled(false);
ui->actionRebuild->setEnabled(false);
ui->actionGenerate_Assembly->setEnabled(false);
ui->actionDebug->setEnabled(false);
ui->btnRunAllProblemCases->setEnabled(false);
} else {
@ -681,6 +682,7 @@ void MainWindow::updateCompileActions()
ui->actionCompile_Run->setEnabled(canRun);
ui->actionRun->setEnabled(canRun);
ui->actionRebuild->setEnabled(true);
ui->actionGenerate_Assembly->setEnabled(!forProject);
ui->actionDebug->setEnabled(canRun);
ui->btnRunAllProblemCases->setEnabled(canRun);
}
@ -1801,7 +1803,7 @@ void MainWindow::checkSyntaxInBack(Editor *e)
}
}
bool MainWindow::compile(bool rebuild)
bool MainWindow::compile(bool rebuild, CppCompileType compileType)
{
mCompilerManager->stopPausing();
CompileTarget target =getCompileTarget();
@ -1837,16 +1839,33 @@ bool MainWindow::compile(bool rebuild)
if (mCompileSuccessionTask) {
Settings::PCompilerSet compilerSet =pSettings->compilerSets().defaultSet();
if (compilerSet) {
mCompileSuccessionTask->execName = compilerSet->getOutputFilename(editor->filename());
mCompileSuccessionTask->isExecutable = compilerSet->isOutputExecutable();
Settings::CompilerSet::CompilationStage stage;
switch(compileType) {
case CppCompileType::GenerateAssemblyOnly:
stage = Settings::CompilerSet::CompilationStage::CompilationProperOnly;
break;
case CppCompileType::PreprocessOnly:
stage = Settings::CompilerSet::CompilationStage::PreprocessingOnly;
break;
default:
stage = compilerSet->compilationStage();
break;
}
mCompileSuccessionTask->execName = compilerSet->getOutputFilename(editor->filename(),stage);
mCompileSuccessionTask->isExecutable = compilerSet->isOutputExecutable(stage);
} else {
mCompileSuccessionTask->execName = changeFileExt(editor->filename(),DEFAULT_EXECUTABLE_SUFFIX);
mCompileSuccessionTask->isExecutable = true;
}
if (!mCompileSuccessionTask->isExecutable) {
Editor *editor = mEditorList->getOpenedEditorByFilename(mCompileSuccessionTask->execName);
if (editor)
mEditorList->closeEditor(editor,false,true);
}
}
stretchMessagesPanel(true);
ui->tabMessages->setCurrentWidget(ui->tabToolsOutput);
mCompilerManager->compile(editor->filename(),editor->fileEncoding(),rebuild);
mCompilerManager->compile(editor->filename(),editor->fileEncoding(),rebuild,compileType);
updateCompileActions();
updateAppTitle();
return true;
@ -1963,7 +1982,7 @@ void MainWindow::runExecutable(RunType runType)
bool isExecutable;
if (compilerSet) {
exeName = compilerSet->getOutputFilename(editor->filename());
isExecutable = compilerSet->compilationStage()==Settings::CompilerSet::CompilationStage::GenerateExecutable;
isExecutable = compilerSet->isOutputExecutable();
} else {
exeName = changeFileExt(editor->filename(), DEFAULT_EXECUTABLE_SUFFIX);
isExecutable = true;
@ -2140,7 +2159,7 @@ void MainWindow::debug()
bool isExecutable;
if (compilerSet) {
filePath = compilerSet->getOutputFilename(e->filename());
isExecutable = compilerSet->compilationStage()==Settings::CompilerSet::CompilationStage::GenerateExecutable;
isExecutable = compilerSet->isOutputExecutable();
} else {
filePath = changeFileExt(e->filename(), DEFAULT_EXECUTABLE_SUFFIX);
isExecutable = true;
@ -7322,6 +7341,20 @@ void MainWindow::doCompileRun(RunType runType)
compile();
}
void MainWindow::doGenerateAssembly()
{
CompileTarget target =getCompileTarget();
QStringList binDirs;
QString execName;
if (target == CompileTarget::File) {
binDirs = getDefaultCompilerSetBinDirs();
}
mCompileSuccessionTask = std::make_shared<CompileSuccessionTask>();
mCompileSuccessionTask->binDirs=binDirs;
mCompileSuccessionTask->type = CompileSuccessionTaskType::RunNormal;
compile(false,CppCompileType::GenerateAssemblyOnly);
}
void MainWindow::updateProblemCaseOutput(POJProblemCase problemCase)
{
if (problemCase->testState == ProblemCaseTestState::Failed) {
@ -8855,3 +8888,9 @@ SearchDialog *MainWindow::searchDialog() const
return mSearchDialog;
}
void MainWindow::on_actionGenerate_Assembly_triggered()
{
doGenerateAssembly();
}

View File

@ -129,7 +129,7 @@ public:
void updateDebuggerSettings();
void updateActionIcons();
void checkSyntaxInBack(Editor* e);
bool compile(bool rebuild=false);
bool compile(bool rebuild=false, CppCompileType compileType=CppCompileType::Normal);
void runExecutable(
const QString& exeName,
const QString& filename,
@ -281,6 +281,7 @@ private:
void showSearchReplacePanel(bool show);
void clearIssues();
void doCompileRun(RunType runType);
void doGenerateAssembly();
void updateProblemCaseOutput(POJProblemCase problemCase);
void applyCurrentProblemCaseChanges();
void showHideInfosTab(QWidget *widget, bool show);
@ -745,6 +746,8 @@ private slots:
void on_actionSwitchHeaderSource_triggered();
void on_actionGenerate_Assembly_triggered();
private:
Ui::MainWindow *ui;
EditorList *mEditorList;

View File

@ -156,6 +156,7 @@
<addaction name="actionRun"/>
<addaction name="actionCompile_Run"/>
<addaction name="actionRebuild"/>
<addaction name="actionGenerate_Assembly"/>
<addaction name="separator"/>
<addaction name="actionRun_Parameters"/>
<addaction name="actionCompiler_Options"/>
@ -3263,6 +3264,11 @@
<string>Switch Header/Source</string>
</property>
</action>
<action name="actionGenerate_Assembly">
<property name="text">
<string>Generate Assembly</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -2464,7 +2464,12 @@ void Settings::CompilerSet::setCompilationStage(CompilationStage newCompilationS
QString Settings::CompilerSet::getOutputFilename(const QString &sourceFilename)
{
switch(compilationStage()) {
return getOutputFilename(sourceFilename, compilationStage());
}
QString Settings::CompilerSet::getOutputFilename(const QString &sourceFilename, CompilationStage stage)
{
switch(stage) {
case Settings::CompilerSet::CompilationStage::PreprocessingOnly:
return changeFileExt(sourceFilename, preprocessingSuffix());
case Settings::CompilerSet::CompilationStage::CompilationProperOnly:
@ -2479,7 +2484,12 @@ QString Settings::CompilerSet::getOutputFilename(const QString &sourceFilename)
bool Settings::CompilerSet::isOutputExecutable()
{
return mCompilationStage == CompilationStage::GenerateExecutable;
return isOutputExecutable(mCompilationStage);
}
bool Settings::CompilerSet::isOutputExecutable(CompilationStage stage)
{
return stage == CompilationStage::GenerateExecutable;
}
const QString &Settings::CompilerSet::assemblingSuffix() const

View File

@ -1331,8 +1331,9 @@ public:
void setCompilationStage(CompilationStage newCompilationStage);
QString getOutputFilename(const QString& sourceFilename);
QString getOutputFilename(const QString& sourceFilename,Settings::CompilerSet::CompilationStage stage);
bool isOutputExecutable();
bool isOutputExecutable(Settings::CompilerSet::CompilationStage stage);
private:
void setDirectories(const QString& binDir, CompilerType mCompilerType);
//load hard defines

View File

@ -4728,6 +4728,10 @@
<source>Switch Header/Source</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Generate Assembly</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NewClassDialog</name>

File diff suppressed because it is too large Load Diff

View File

@ -4569,6 +4569,10 @@
<source>Switch Header/Source</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Generate Assembly</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NewClassDialog</name>

View File

@ -16,10 +16,34 @@
*/
#include "asm.h"
#include "../Constants.h"
#include <QDebug>
namespace QSynedit {
const QSet<QString> ASMHighlighter::Keywords {
"movb","movw","movl","movq",
"leab","leaw","leal","leaq",
"incb","incw","incl","incq",
"decb","decw","decl","decq",
"addb","addw","addl","addq",
"subb","subw","subl","subq",
"imulb","imulw","imull","imulq",
"divb","divw","divl","divq",
"xorb","xorw","xorl","xorq",
"orb","orw","orl","orq",
"andb","andw","andl","andq",
"salb","salw","sall","salq",
"shlb","shlw","shll","shlq",
"sarb","sarw","sarl","sarq",
"shrb","shrw","shrl","shrq",
"cmpb","cmpw","cmpl","cmpq",
"testb","testw","testl","testq",
"pushq","popq",
"cmove", "cmovz", "cmovne", "cmovnz",
"cmovs", "cmovns", "cmovg", "cmovge",
"cmovl", "cmovle", "cmova", "cmovae",
"cmovb", "cmovbe", "cmovnbe","cmovnb",
"cmovnae","cmovna",
"aaa","aad","aam","adc","add","and","arpl","bound","bsf","bsr","bswap","bt","btc","btr","bts",
"call","cbw","cdq","clc","cld","cli","clts","cmc","cmp","cmps","cmpsb","cmpsd","cmpsw",
"cmpxchg","cwd","cwde","daa","das","dec","div","emms","enter","f2xm1","fabs","fadd","faddp","fbld",
@ -98,7 +122,7 @@ void ASMHighlighter::IdentProc()
}
QString s = mLineString.mid(start,mRun-start);
if (Keywords.contains(s)) {
mTokenID = TokenId::Key;
mTokenID = TokenId::rainbow;
} else {
mTokenID = TokenId::Identifier;
}
@ -130,7 +154,8 @@ void ASMHighlighter::NumberProc()
while (true) {
QChar ch = mLine[mRun];
if (!((ch>='0' && ch<='9') || (ch=='.') || (ch >= 'a' && ch<='f')
|| (ch=='h') || (ch >= 'A' && ch<='F') || (ch == 'H')))
|| (ch=='h') || (ch >= 'A' && ch<='F') || (ch == 'H')
|| (ch == 'x')))
break;
mRun++;
}
@ -181,6 +206,7 @@ void ASMHighlighter::StringProc()
mTokenID = TokenId::String;
if ((mRun+2 < mLineString.size()) && (mLine[mRun + 1] == '\"') && (mLine[mRun + 2] == '\"'))
mRun += 2;
mRun+=1;
while (true) {
if (mLine[mRun] == 0 || mLine[mRun] == '\r' || mLine[mRun] == '\n')
break;
@ -231,7 +257,7 @@ PHighlighterAttribute ASMHighlighter::getTokenAttribute() const
return mCommentAttribute;
case TokenId::Identifier:
return mIdentifierAttribute;
case TokenId::Key:
case TokenId::rainbow:
return mKeywordAttribute;
case TokenId::Number:
return mNumberAttribute;

View File

@ -26,7 +26,7 @@ class ASMHighlighter : public Highlighter
enum class TokenId {
Comment,
Identifier,
Key,
rainbow, // add mov etc
Null,
Number,
Space,
@ -91,6 +91,8 @@ public:
// SynHighlighter interface
public:
QSet<QString> keywords() const override;
const PHighlighterAttribute &directiveAttribute() const;
const PHighlighterAttribute &labelAttribute() const;
};
}

View File

@ -103,6 +103,11 @@ QString Highlighter::foldString()
return " ... }";
}
bool Highlighter::supportBraceLevel()
{
return false;
}
bool Highlighter::isSpaceChar(const QChar &ch)
{
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';

View File

@ -154,6 +154,7 @@ public:
virtual QString foldString();
virtual bool supportBraceLevel();
virtual bool isSpaceChar(const QChar& ch);
virtual bool isWordBreakChar(const QChar& ch);
bool enabled() const;

View File

@ -1399,6 +1399,11 @@ void CppHighlighter::setCustomTypeKeywords(const QSet<QString> &newCustomTypeKey
mCustomTypeKeywords = newCustomTypeKeywords;
}
bool CppHighlighter::supportBraceLevel()
{
return true;
}
bool CppHighlighter::getTokenFinished() const
{
if (mTokenId == TokenId::Comment

View File

@ -202,6 +202,10 @@ public:
QString foldString() override;
const QSet<QString> &customTypeKeywords() const;
void setCustomTypeKeywords(const QSet<QString> &newCustomTypeKeywords);
// Highlighter interface
public:
bool supportBraceLevel() override;
};
}

View File

@ -1471,4 +1471,9 @@ QSet<QString> GLSLHighlighter::keywords() const
{
return Keywords;
}
bool GLSLHighlighter::supportBraceLevel()
{
return true;
}
}

View File

@ -192,6 +192,10 @@ public:
// SynHighlighter interface
public:
QSet<QString> keywords() const override;
// Highlighter interface
public:
bool supportBraceLevel() override;
};
}